From 44d565dcd6c3b2d2f7795b881f35aa8bfcf1d4dd Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 28 Nov 2024 09:58:45 +0100 Subject: [PATCH 01/29] [PPANTT-191] configured pom, updated package name, replace javax dependency with jakarta and format code --- pom.xml | 11 +- .../gps/service}/Application.java | 9 +- .../gps/service}/config/LoggingAspect.java | 51 ++-- .../config/MappingsConfiguration.java | 2 +- .../mdb/gps/service/config/OpenApiConfig.java | 146 +++++++++++ .../mdb/gps/service/config/RequestFilter.java | 59 +++++ .../gps/service/config/ResponseValidator.java | 55 ++++ .../service/config/WebMvcConfiguration.java | 28 +++ .../service}/controller/HomeController.java | 27 +- .../mdb/gps/service/exception/AppError.java | 27 ++ .../gps/service/exception/AppException.java | 90 +++++++ .../gps/service/exception/ErrorHandler.java | 235 ++++++++++++++++++ .../service}/model/AppCorsConfiguration.java | 6 +- .../gps/service}/model/AppInfo.java | 8 +- .../mdb/gps/service/model/ProblemJson.java | 39 +++ .../gps/service}/util/CommonUtility.java | 5 +- .../mdb/gps/service/util/Constants.java | 9 + .../microservice/config/OpenApiConfig.java | 129 ---------- .../microservice/config/RequestFilter.java | 58 ----- .../config/ResponseValidator.java | 52 ---- .../config/WebMvcConfiguration.java | 30 --- .../microservice/exception/AppError.java | 30 --- .../microservice/exception/AppException.java | 87 ------- .../microservice/exception/ErrorHandler.java | 220 ---------------- .../microservice/model/ProblemJson.java | 40 --- .../pagopa/microservice/util/Constants.java | 11 - .../pagopa/microservice/ApplicationTest.java | 14 +- .../microservice/OpenApiGenerationTest.java | 60 ++--- 28 files changed, 784 insertions(+), 754 deletions(-) rename src/main/java/it/gov/pagopa/{microservice => mdb/gps/service}/Application.java (51%) rename src/main/java/it/gov/pagopa/{microservice => mdb/gps/service}/config/LoggingAspect.java (80%) rename src/main/java/it/gov/pagopa/{microservice => mdb/gps/service}/config/MappingsConfiguration.java (90%) create mode 100644 src/main/java/it/gov/pagopa/mdb/gps/service/config/OpenApiConfig.java create mode 100644 src/main/java/it/gov/pagopa/mdb/gps/service/config/RequestFilter.java create mode 100644 src/main/java/it/gov/pagopa/mdb/gps/service/config/ResponseValidator.java create mode 100644 src/main/java/it/gov/pagopa/mdb/gps/service/config/WebMvcConfiguration.java rename src/main/java/it/gov/pagopa/{microservice => mdb/gps/service}/controller/HomeController.java (51%) create mode 100644 src/main/java/it/gov/pagopa/mdb/gps/service/exception/AppError.java create mode 100644 src/main/java/it/gov/pagopa/mdb/gps/service/exception/AppException.java create mode 100644 src/main/java/it/gov/pagopa/mdb/gps/service/exception/ErrorHandler.java rename src/main/java/it/gov/pagopa/{microservice => mdb/gps/service}/model/AppCorsConfiguration.java (83%) rename src/main/java/it/gov/pagopa/{microservice => mdb/gps/service}/model/AppInfo.java (75%) create mode 100644 src/main/java/it/gov/pagopa/mdb/gps/service/model/ProblemJson.java rename src/main/java/it/gov/pagopa/{microservice => mdb/gps/service}/util/CommonUtility.java (97%) create mode 100644 src/main/java/it/gov/pagopa/mdb/gps/service/util/Constants.java delete mode 100644 src/main/java/it/gov/pagopa/microservice/config/OpenApiConfig.java delete mode 100644 src/main/java/it/gov/pagopa/microservice/config/RequestFilter.java delete mode 100644 src/main/java/it/gov/pagopa/microservice/config/ResponseValidator.java delete mode 100644 src/main/java/it/gov/pagopa/microservice/config/WebMvcConfiguration.java delete mode 100644 src/main/java/it/gov/pagopa/microservice/exception/AppError.java delete mode 100644 src/main/java/it/gov/pagopa/microservice/exception/AppException.java delete mode 100644 src/main/java/it/gov/pagopa/microservice/exception/ErrorHandler.java delete mode 100644 src/main/java/it/gov/pagopa/microservice/model/ProblemJson.java delete mode 100644 src/main/java/it/gov/pagopa/microservice/util/Constants.java diff --git a/pom.xml b/pom.xml index 8b8fb4c..460d4b4 100644 --- a/pom.xml +++ b/pom.xml @@ -11,10 +11,10 @@ it.gov.pagopa - microservice + pagopa-gps-mdb-service 0.0.0 - Your Name - Your description + MDB GPS Service + MDB GPS Service 17 @@ -108,11 +108,6 @@ true - - junit - junit - test - co.elastic.logging logback-ecs-encoder diff --git a/src/main/java/it/gov/pagopa/microservice/Application.java b/src/main/java/it/gov/pagopa/mdb/gps/service/Application.java similarity index 51% rename from src/main/java/it/gov/pagopa/microservice/Application.java rename to src/main/java/it/gov/pagopa/mdb/gps/service/Application.java index 465b6cb..cad8802 100644 --- a/src/main/java/it/gov/pagopa/microservice/Application.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/Application.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.microservice; // TODO: refactor the package +package it.gov.pagopa.mdb.gps.service; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -6,8 +6,7 @@ @SpringBootApplication public class Application { - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } - + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } } diff --git a/src/main/java/it/gov/pagopa/microservice/config/LoggingAspect.java b/src/main/java/it/gov/pagopa/mdb/gps/service/config/LoggingAspect.java similarity index 80% rename from src/main/java/it/gov/pagopa/microservice/config/LoggingAspect.java rename to src/main/java/it/gov/pagopa/mdb/gps/service/config/LoggingAspect.java index 8990632..f923caf 100644 --- a/src/main/java/it/gov/pagopa/microservice/config/LoggingAspect.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/config/LoggingAspect.java @@ -1,7 +1,10 @@ -package it.gov.pagopa.microservice.config; +package it.gov.pagopa.mdb.gps.service.config; -import it.gov.pagopa.microservice.exception.AppError; -import it.gov.pagopa.microservice.model.ProblemJson; +import it.gov.pagopa.mdb.gps.service.exception.AppError; +import it.gov.pagopa.mdb.gps.service.model.ProblemJson; +import jakarta.annotation.PostConstruct; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; @@ -16,14 +19,11 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.util.HashMap; import java.util.Map; import java.util.UUID; -import static it.gov.pagopa.microservice.util.CommonUtility.deNull; +import static it.gov.pagopa.mdb.gps.service.util.CommonUtility.deNull; @Aspect @@ -42,21 +42,26 @@ public class LoggingAspect { public static final String OPERATION_ID = "operationId"; public static final String ARGS = "args"; - @Autowired HttpServletRequest httRequest; - - @Autowired HttpServletResponse httpResponse; + private final String name; + private final String version; + private final String environment; - @Value("${info.application.name}") - private String name; - - @Value("${info.application.version}") - private String version; - - @Value("${info.properties.environment}") - private String environment; - + @Autowired + public LoggingAspect( + HttpServletRequest httRequest, + HttpServletResponse httpResponse, + @Value("${info.application.name}") String name, + @Value("${info.application.version}") String version, + @Value("${info.properties.environment}") String environment + ) { + this.httRequest = httRequest; + this.httpResponse = httpResponse; + this.name = name; + this.version = version; + this.environment = environment; + } @Pointcut("@within(org.springframework.web.bind.annotation.RestController)") public void restController() { @@ -86,7 +91,7 @@ public Object logApiInvocation(ProceedingJoinPoint joinPoint) throws Throwable { MDC.put(METHOD, joinPoint.getSignature().getName()); MDC.put(START_TIME, String.valueOf(System.currentTimeMillis())); MDC.put(OPERATION_ID, UUID.randomUUID().toString()); - if(MDC.get(REQUEST_ID) == null) { + if (MDC.get(REQUEST_ID) == null) { var requestId = UUID.randomUUID().toString(); MDC.put(REQUEST_ID, requestId); } @@ -129,20 +134,20 @@ public Object logTrace(ProceedingJoinPoint joinPoint) throws Throwable { } private static String getDetail(ResponseEntity result) { - if(result != null && result.getBody() != null && result.getBody().getDetail() != null) { + if (result != null && result.getBody() != null && result.getBody().getDetail() != null) { return result.getBody().getDetail(); } else return AppError.UNKNOWN.getDetails(); } private static String getTitle(ResponseEntity result) { - if(result != null && result.getBody() != null && result.getBody().getTitle() != null) { + if (result != null && result.getBody() != null && result.getBody().getTitle() != null) { return result.getBody().getTitle(); } else return AppError.UNKNOWN.getTitle(); } public static String getExecutionTime() { String startTime = MDC.get(START_TIME); - if(startTime != null) { + if (startTime != null) { long endTime = System.currentTimeMillis(); long executionTime = endTime - Long.parseLong(startTime); return String.valueOf(executionTime); diff --git a/src/main/java/it/gov/pagopa/microservice/config/MappingsConfiguration.java b/src/main/java/it/gov/pagopa/mdb/gps/service/config/MappingsConfiguration.java similarity index 90% rename from src/main/java/it/gov/pagopa/microservice/config/MappingsConfiguration.java rename to src/main/java/it/gov/pagopa/mdb/gps/service/config/MappingsConfiguration.java index b403822..d5e0159 100644 --- a/src/main/java/it/gov/pagopa/microservice/config/MappingsConfiguration.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/config/MappingsConfiguration.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.microservice.config; +package it.gov.pagopa.mdb.gps.service.config; import org.modelmapper.ModelMapper; diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/config/OpenApiConfig.java b/src/main/java/it/gov/pagopa/mdb/gps/service/config/OpenApiConfig.java new file mode 100644 index 0000000..1e8c1bc --- /dev/null +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/config/OpenApiConfig.java @@ -0,0 +1,146 @@ +package it.gov.pagopa.mdb.gps.service.config; + +import static it.gov.pagopa.mdb.gps.service.util.Constants.HEADER_REQUEST_ID; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Paths; +import io.swagger.v3.oas.models.headers.Header; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.media.StringSchema; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.responses.ApiResponses; +import io.swagger.v3.oas.models.security.SecurityScheme; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +import io.swagger.v3.oas.models.servers.Server; +import io.swagger.v3.oas.models.servers.ServerVariable; +import io.swagger.v3.oas.models.servers.ServerVariables; +import org.springdoc.core.customizers.OpenApiCustomiser; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class OpenApiConfig { + + public static final String BASE_PATH = "/mdb/gps/service/v1"; + + @Bean + public OpenAPI customOpenAPI( + @Value("${info.application.artifactId}") String appName, + @Value("${info.application.description}") String appDescription, + @Value("${info.application.version}") String appVersion + ) { + return new OpenAPI() + .servers(List.of(new Server().url("http://localhost:8080"), + new Server().url("https://{host}{basePath}") + .variables(new ServerVariables() + .addServerVariable("host", + new ServerVariable()._enum(List.of("api.dev.platform.pagopa.it", "api.uat.platform.pagopa.it", "api.platform.pagopa.it")) + ._default("api.dev.platform.pagopa.it")) + .addServerVariable("basePath", new ServerVariable()._default(BASE_PATH)) + ))) + .components( + new Components() + .addSecuritySchemes( + "ApiKey", + new SecurityScheme() + .type(SecurityScheme.Type.APIKEY) + .description("The API key to access this function app.") + .name("Ocp-Apim-Subscription-Key") + .in(SecurityScheme.In.HEADER))) + .info( + new Info() + .title(appName) + .version(appVersion) + .description(appDescription) + .termsOfService("https://www.pagopa.gov.it/")); + } + + @Bean + public OpenApiCustomiser sortOperationsAlphabetically() { + return openApi -> { + Paths paths = + openApi + .getPaths() + .entrySet() + .stream() + .sorted(Map.Entry.comparingByKey()) + .collect( + Paths::new, + (map, item) -> map.addPathItem(item.getKey(), item.getValue()), + Paths::putAll); + + paths.forEach( + (key, value) -> + value + .readOperations() + .forEach( + operation -> { + var responses = + operation + .getResponses() + .entrySet() + .stream() + .sorted(Map.Entry.comparingByKey()) + .collect( + ApiResponses::new, + (map, item) -> + map.addApiResponse(item.getKey(), item.getValue()), + ApiResponses::putAll); + operation.setResponses(responses); + })); + openApi.setPaths(paths); + }; + } + + @Bean + public OpenApiCustomiser addCommonHeaders() { + return openApi -> + openApi + .getPaths() + .forEach( + (key, value) -> { + + // add Request-ID as request header + var header = + Optional.ofNullable(value.getParameters()) + .orElse(Collections.emptyList()) + .parallelStream() + .filter(Objects::nonNull) + .anyMatch(elem -> HEADER_REQUEST_ID.equals(elem.getName())); + if (!header) { + value.addParametersItem( + new Parameter() + .in("header") + .name(HEADER_REQUEST_ID) + .schema(new StringSchema()) + .description( + "This header identifies the call, if not passed it is self-generated. This ID is returned in the response.")); + } + + // add Request-ID as response header + value + .readOperations() + .forEach( + operation -> + operation + .getResponses() + .values() + .forEach( + response -> + response.addHeaderObject( + HEADER_REQUEST_ID, + new Header() + .schema(new StringSchema()) + .description( + "This header identifies the call")))); + }); + } +} diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/config/RequestFilter.java b/src/main/java/it/gov/pagopa/mdb/gps/service/config/RequestFilter.java new file mode 100644 index 0000000..5f58ee5 --- /dev/null +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/config/RequestFilter.java @@ -0,0 +1,59 @@ +package it.gov.pagopa.mdb.gps.service.config; + +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.MDC; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.UUID; + +import static it.gov.pagopa.mdb.gps.service.util.Constants.HEADER_REQUEST_ID; + +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +@Slf4j +public class RequestFilter implements Filter { + + /** + * Get the request ID from the custom header "X-Request-Id" if present, otherwise it generates + * one. Set the X-Request-Id value in the {@code response} and in the MDC + * + * @param request http request + * @param response http response + * @param chain next filter + * @throws IOException if an I/O error occurs during this filter's processing of the request + * @throws ServletException if the processing fails for any other reason + */ + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + try { + HttpServletRequest httRequest = (HttpServletRequest) request; + + // get requestId from header or generate one + String requestId = httRequest.getHeader(HEADER_REQUEST_ID); + if (requestId == null || requestId.isEmpty()) { + requestId = UUID.randomUUID().toString(); + } + + // set requestId in MDC + MDC.put("requestId", requestId); + + // set requestId in the response header + ((HttpServletResponse) response).setHeader(HEADER_REQUEST_ID, requestId); + chain.doFilter(request, response); + } finally { + MDC.clear(); + } + } + +} diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/config/ResponseValidator.java b/src/main/java/it/gov/pagopa/mdb/gps/service/config/ResponseValidator.java new file mode 100644 index 0000000..0a2ae65 --- /dev/null +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/config/ResponseValidator.java @@ -0,0 +1,55 @@ +package it.gov.pagopa.mdb.gps.service.config; + +import it.gov.pagopa.mdb.gps.service.exception.AppException; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.Validator; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; + +import java.util.Set; + +@Aspect +@Component +public class ResponseValidator { + + private final Validator validator; + + @Autowired + public ResponseValidator(Validator validator) { + this.validator = validator; + } + + /** + * This method validates the response annotated with the {@link jakarta.validation.Constraint} + * + * @param joinPoint not used + * @param result the response to validate + */ + @AfterReturning(pointcut = "execution(* it.gov.pagopa.mdb.gps.service.controller.*.*(..))", returning = "result") + public void validateResponse(JoinPoint joinPoint, Object result) { + if (result instanceof ResponseEntity) { + validateResponse((ResponseEntity) result); + } + } + + private void validateResponse(ResponseEntity response) { + if (response.getBody() != null) { + Set> validationResults = validator.validate(response.getBody()); + + if (!validationResults.isEmpty()) { + var sb = new StringBuilder(); + for (ConstraintViolation error : validationResults) { + sb.append(error.getPropertyPath()).append(" ").append(error.getMessage()).append(". "); + } + var msg = StringUtils.chop(sb.toString()); + throw new AppException(HttpStatus.INTERNAL_SERVER_ERROR, "Invalid response", msg); + } + } + } +} diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/config/WebMvcConfiguration.java b/src/main/java/it/gov/pagopa/mdb/gps/service/config/WebMvcConfiguration.java new file mode 100644 index 0000000..f6b3397 --- /dev/null +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/config/WebMvcConfiguration.java @@ -0,0 +1,28 @@ +package it.gov.pagopa.mdb.gps.service.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import it.gov.pagopa.mdb.gps.service.model.AppCorsConfiguration; +import lombok.SneakyThrows; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebMvcConfiguration implements WebMvcConfigurer { + + @Value("${cors.configuration}") + private String corsConfiguration; + + @SneakyThrows + @Override + public void addCorsMappings(CorsRegistry registry) { + AppCorsConfiguration appCorsConfiguration = new ObjectMapper().readValue(corsConfiguration, + AppCorsConfiguration.class); + registry.addMapping("/**") + .allowedOrigins(appCorsConfiguration.getOrigins()) + .allowedMethods(appCorsConfiguration.getMethods()); + } +} + + diff --git a/src/main/java/it/gov/pagopa/microservice/controller/HomeController.java b/src/main/java/it/gov/pagopa/mdb/gps/service/controller/HomeController.java similarity index 51% rename from src/main/java/it/gov/pagopa/microservice/controller/HomeController.java rename to src/main/java/it/gov/pagopa/mdb/gps/service/controller/HomeController.java index 70b6dd1..7d96f77 100644 --- a/src/main/java/it/gov/pagopa/microservice/controller/HomeController.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/controller/HomeController.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.microservice.controller; +package it.gov.pagopa.mdb.gps.service.controller; import io.swagger.v3.oas.annotations.Hidden; import org.springframework.beans.factory.annotation.Value; @@ -11,20 +11,19 @@ @Validated public class HomeController { - @Value("${server.servlet.context-path}") - String basePath; + @Value("${server.servlet.context-path}") + String basePath; - /** - * @return redirect to Swagger page documentation - */ - @Hidden - @GetMapping("") - public RedirectView home() { - if (!basePath.endsWith("/")) { - basePath += "/"; + /** + * @return redirect to Swagger page documentation + */ + @Hidden + @GetMapping("") + public RedirectView home() { + if (!basePath.endsWith("/")) { + basePath += "/"; + } + return new RedirectView(basePath + "swagger-ui.html"); } - return new RedirectView(basePath + "swagger-ui.html"); - } - } diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/exception/AppError.java b/src/main/java/it/gov/pagopa/mdb/gps/service/exception/AppError.java new file mode 100644 index 0000000..2acbc10 --- /dev/null +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/exception/AppError.java @@ -0,0 +1,27 @@ +package it.gov.pagopa.mdb.gps.service.exception; + +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +public enum AppError { + INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "Internal Server Error", "Something was wrong"), + BAD_REQUEST(HttpStatus.INTERNAL_SERVER_ERROR, "Bad Request", "%s"), + UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "Unauthorized", "Error during authentication"), + FORBIDDEN(HttpStatus.FORBIDDEN, "Forbidden", "This method is forbidden"), + RESPONSE_NOT_READABLE(HttpStatus.BAD_GATEWAY, "Response Not Readable", "The response body is not readable"), + + UNKNOWN(null, null, null); + + public final HttpStatus httpStatus; + public final String title; + public final String details; + + AppError(HttpStatus httpStatus, String title, String details) { + this.httpStatus = httpStatus; + this.title = title; + this.details = details; + } +} + + diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/exception/AppException.java b/src/main/java/it/gov/pagopa/mdb/gps/service/exception/AppException.java new file mode 100644 index 0000000..c3af0c4 --- /dev/null +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/exception/AppException.java @@ -0,0 +1,90 @@ +package it.gov.pagopa.mdb.gps.service.exception; + +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.springframework.http.HttpStatus; +import org.springframework.validation.annotation.Validated; + +import java.util.Formatter; + +/** + * Custom exception. + *

See {@link ErrorHandler} + */ +@EqualsAndHashCode(callSuper = true) +@Value +@Validated +public class AppException extends RuntimeException { + + /** + * title returned to the response when this exception occurred + */ + String title; + + /** + * http status returned to the response when this exception occurred + */ + HttpStatus httpStatus; + + /** + * @param httpStatus HTTP status returned to the response + * @param title title returned to the response when this exception occurred + * @param message the detail message returend to the response + * @param cause The cause of this {@link AppException} + */ + public AppException( + @NotNull HttpStatus httpStatus, @NotNull String title, + @NotNull String message, Throwable cause + ) { + super(message, cause); + this.title = title; + this.httpStatus = httpStatus; + } + + /** + * @param httpStatus HTTP status returned to the response + * @param title title returned to the response when this exception occurred + * @param message the detail message returend to the response + */ + public AppException(@NotNull HttpStatus httpStatus, @NotNull String title, @NotNull String message) { + super(message); + this.title = title; + this.httpStatus = httpStatus; + } + + + /** + * @param appError Response template returned to the response + * @param args {@link Formatter} replaces the placeholders in "details" string of + * {@link AppError} with the arguments. If there are more arguments than format + * specifiers, the extra arguments are ignored. + */ + public AppException(@NotNull AppError appError, Object... args) { + super(formatDetails(appError, args)); + this.httpStatus = appError.httpStatus; + this.title = appError.title; + } + + /** + * @param appError Response template returned to the response + * @param cause The cause of this {@link AppException} + * @param args Arguments for the details of {@link AppError} replaced by the + * {@link Formatter}. If there are more arguments than format specifiers, the + * extra arguments are ignored. + */ + public AppException(@NotNull AppError appError, Throwable cause, Object... args) { + super(formatDetails(appError, args), cause); + this.httpStatus = appError.httpStatus; + this.title = appError.title; + } + + private static String formatDetails(AppError appError, Object[] args) { + return String.format(appError.details, args); + } + + @Override + public String toString() { + return "AppException(" + httpStatus + ", " + title + ")" + super.toString(); + } +} diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/exception/ErrorHandler.java b/src/main/java/it/gov/pagopa/mdb/gps/service/exception/ErrorHandler.java new file mode 100644 index 0000000..2c655a1 --- /dev/null +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/exception/ErrorHandler.java @@ -0,0 +1,235 @@ +package it.gov.pagopa.mdb.gps.service.exception; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import feign.FeignException; +import it.gov.pagopa.mdb.gps.service.model.ProblemJson; +import jakarta.validation.ConstraintViolationException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.TypeMismatchException; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.MissingServletRequestParameterException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +/** + * All Exceptions are handled by this class + */ +@ControllerAdvice +@Slf4j +public class ErrorHandler extends ResponseEntityExceptionHandler { + + /** + * Handle if the input request is not a valid JSON + * + * @param ex {@link HttpMessageNotReadableException} exception raised + * @param headers of the response + * @param status of the response + * @param request from frontend + * @return a {@link ProblemJson} as response with the cause and with a 400 as HTTP status + */ + @Override + public ResponseEntity handleHttpMessageNotReadable( + HttpMessageNotReadableException ex, + HttpHeaders headers, + HttpStatusCode status, + WebRequest request + ) { + log.warn("Input not readable: ", ex); + var errorResponse = ProblemJson.builder() + .status(HttpStatus.BAD_REQUEST.value()) + .title(AppError.BAD_REQUEST.getTitle()) + .detail("Invalid input format") + .build(); + return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); + } + + /** + * Handle if missing some request parameters in the request + * + * @param ex {@link MissingServletRequestParameterException} exception raised + * @param headers of the response + * @param status of the response + * @param request from frontend + * @return a {@link ProblemJson} as response with the cause and with a 400 as HTTP status + */ + @Override + public ResponseEntity handleMissingServletRequestParameter( + MissingServletRequestParameterException ex, + HttpHeaders headers, + HttpStatusCode status, + WebRequest request + ) { + log.warn("Missing request parameter: ", ex); + var errorResponse = ProblemJson.builder() + .status(HttpStatus.BAD_REQUEST.value()) + .title(AppError.BAD_REQUEST.getTitle()) + .detail(ex.getMessage()) + .build(); + return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); + } + + + /** + * Customize the response for TypeMismatchException. + * + * @param ex the exception + * @param headers the headers to be written to the response + * @param status the selected response status + * @param request the current request + * @return a {@code ResponseEntity} instance + */ + @Override + protected ResponseEntity handleTypeMismatch( + TypeMismatchException ex, + HttpHeaders headers, + HttpStatusCode status, + WebRequest request + ) { + log.warn("Type mismatch: ", ex); + var errorResponse = ProblemJson.builder() + .status(HttpStatus.BAD_REQUEST.value()) + .title(AppError.BAD_REQUEST.getTitle()) + .detail(String.format("Invalid value %s for property %s", ex.getValue(), + ((MethodArgumentTypeMismatchException) ex).getName())) + .build(); + return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); + } + + /** + * Handle if validation constraints are unsatisfied + * + * @param ex {@link MethodArgumentNotValidException} exception raised + * @param headers of the response + * @param status of the response + * @param request from frontend + * @return a {@link ProblemJson} as response with the cause and with a 400 as HTTP status + */ + @Override + protected ResponseEntity handleMethodArgumentNotValid( + MethodArgumentNotValidException ex, + HttpHeaders headers, + HttpStatusCode status, + WebRequest request + ) { + List details = new ArrayList<>(); + for (FieldError error : ex.getBindingResult().getFieldErrors()) { + details.add(error.getField() + ": " + error.getDefaultMessage()); + } + var detailsMessage = String.join(", ", details); + log.warn("Input not valid: " + detailsMessage); + var errorResponse = ProblemJson.builder() + .status(HttpStatus.BAD_REQUEST.value()) + .title(AppError.BAD_REQUEST.getTitle()) + .detail(detailsMessage) + .build(); + return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); + } + + @ExceptionHandler({ConstraintViolationException.class}) + public ResponseEntity handleConstraintViolationException( + final ConstraintViolationException ex, + final WebRequest request + ) { + log.warn("Validation Error raised:", ex); + var errorResponse = ProblemJson.builder() + .status(HttpStatus.BAD_REQUEST.value()) + .title(AppError.BAD_REQUEST.getTitle()) + .detail(ex.getMessage()) + .build(); + return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); + } + + /** + * Handle if a {@link FeignException} is raised + * + * @param ex {@link FeignException} exception raised + * @param request from frontend + * @return a {@link ProblemJson} as response with the cause and with an appropriated HTTP status + */ + @ExceptionHandler({FeignException.class}) + public ResponseEntity handleFeignException(final FeignException ex, final WebRequest request) { + log.warn("FeignException raised: ", ex); + + ProblemJson problem; + if (ex.responseBody().isPresent()) { + var body = new String(ex.responseBody().get().array(), StandardCharsets.UTF_8); + try { + problem = new ObjectMapper().readValue(body, ProblemJson.class); + } catch (JsonProcessingException e) { + problem = ProblemJson.builder() + .status(HttpStatus.BAD_GATEWAY.value()) + .title(AppError.RESPONSE_NOT_READABLE.getTitle()) + .detail(AppError.RESPONSE_NOT_READABLE.getDetails()) + .build(); + } + } else { + problem = ProblemJson.builder() + .status(HttpStatus.BAD_GATEWAY.value()) + .title("No Response Body") + .detail("Error with external dependency") + .build(); + } + + return new ResponseEntity<>(problem, HttpStatus.valueOf(problem.getStatus())); + } + + /** + * Handle if a {@link AppException} is raised + * + * @param ex {@link AppException} exception raised + * @param request from frontend + * @return a {@link ProblemJson} as response with the cause and with an appropriated HTTP status + */ + @ExceptionHandler({AppException.class}) + public ResponseEntity handleAppException( + final AppException ex, + final WebRequest request + ) { + if (ex.getCause() != null) { + log.warn("App Exception raised: {}\nCause of the App Exception: ", ex.getMessage(), ex.getCause()); + } else { + log.warn("App Exception raised: ", ex); + } + var errorResponse = ProblemJson.builder() + .status(ex.getHttpStatus().value()) + .title(ex.getTitle()) + .detail(ex.getMessage()) + .build(); + return new ResponseEntity<>(errorResponse, ex.getHttpStatus()); + } + + /** + * Handle if a {@link Exception} is raised + * + * @param ex {@link Exception} exception raised + * @param request from frontend + * @return a {@link ProblemJson} as response with the cause and with 500 as HTTP status + */ + @ExceptionHandler({Exception.class}) + public ResponseEntity handleGenericException( + final Exception ex, + final WebRequest request + ) { + log.error("Generic Exception raised:", ex); + var errorResponse = ProblemJson.builder() + .status(HttpStatus.INTERNAL_SERVER_ERROR.value()) + .title(AppError.INTERNAL_SERVER_ERROR.getTitle()) + .detail(ex.getMessage()) + .build(); + return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR); + } +} diff --git a/src/main/java/it/gov/pagopa/microservice/model/AppCorsConfiguration.java b/src/main/java/it/gov/pagopa/mdb/gps/service/model/AppCorsConfiguration.java similarity index 83% rename from src/main/java/it/gov/pagopa/microservice/model/AppCorsConfiguration.java rename to src/main/java/it/gov/pagopa/mdb/gps/service/model/AppCorsConfiguration.java index 8d99b89..b636528 100644 --- a/src/main/java/it/gov/pagopa/microservice/model/AppCorsConfiguration.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/model/AppCorsConfiguration.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.microservice.model; +package it.gov.pagopa.mdb.gps.service.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; @@ -18,6 +18,6 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class AppCorsConfiguration { - private String[] origins; - private String[] methods; + private String[] origins; + private String[] methods; } diff --git a/src/main/java/it/gov/pagopa/microservice/model/AppInfo.java b/src/main/java/it/gov/pagopa/mdb/gps/service/model/AppInfo.java similarity index 75% rename from src/main/java/it/gov/pagopa/microservice/model/AppInfo.java rename to src/main/java/it/gov/pagopa/mdb/gps/service/model/AppInfo.java index d381de0..536eace 100644 --- a/src/main/java/it/gov/pagopa/microservice/model/AppInfo.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/model/AppInfo.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.microservice.model; +package it.gov.pagopa.mdb.gps.service.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.AccessLevel; @@ -16,7 +16,7 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class AppInfo { - private String name; - private String version; - private String environment; + private String name; + private String version; + private String environment; } diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/model/ProblemJson.java b/src/main/java/it/gov/pagopa/mdb/gps/service/model/ProblemJson.java new file mode 100644 index 0000000..01c3f38 --- /dev/null +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/model/ProblemJson.java @@ -0,0 +1,39 @@ +package it.gov.pagopa.mdb.gps.service.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +/** + * Object returned as response in case of an error. + *

See {@link it.gov.pagopa.mdb.gps.service.exception.ErrorHandler} + */ +@Data +@Builder(toBuilder = true) +@NoArgsConstructor +@AllArgsConstructor +@ToString +@JsonIgnoreProperties(ignoreUnknown = true) +public class ProblemJson { + + @JsonProperty("title") + @Schema(description = "A short, summary of the problem type. Written in english and readable for engineers (usually not suited for non technical stakeholders and not localized); example: Service Unavailable") + private String title; + + @JsonProperty("status") + @Schema(example = "200", description = "The HTTP status code generated by the origin server for this occurrence of the problem.") + @Min(100) + @Max(600) + private Integer status; + + @JsonProperty("detail") + @Schema(example = "There was an error processing the request", description = "A human readable explanation specific to this occurrence of the problem.") + private String detail; +} diff --git a/src/main/java/it/gov/pagopa/microservice/util/CommonUtility.java b/src/main/java/it/gov/pagopa/mdb/gps/service/util/CommonUtility.java similarity index 97% rename from src/main/java/it/gov/pagopa/microservice/util/CommonUtility.java rename to src/main/java/it/gov/pagopa/mdb/gps/service/util/CommonUtility.java index f080c47..ff5a1b7 100644 --- a/src/main/java/it/gov/pagopa/microservice/util/CommonUtility.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/util/CommonUtility.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.microservice.util; +package it.gov.pagopa.mdb.gps.service.util; import lombok.AccessLevel; import lombok.NoArgsConstructor; @@ -10,7 +10,6 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public class CommonUtility { - /** * @param value value to deNullify. * @return return empty string if value is null @@ -50,6 +49,4 @@ public static byte[] createCsv(List headers, List> rows) { public static long getTimelapse(long startTime) { return Calendar.getInstance().getTimeInMillis() - startTime; } - - } diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/util/Constants.java b/src/main/java/it/gov/pagopa/mdb/gps/service/util/Constants.java new file mode 100644 index 0000000..fd1b860 --- /dev/null +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/util/Constants.java @@ -0,0 +1,9 @@ +package it.gov.pagopa.mdb.gps.service.util; + +import lombok.experimental.UtilityClass; + +@UtilityClass +public class Constants { + + public static final String HEADER_REQUEST_ID = "X-Request-Id"; +} diff --git a/src/main/java/it/gov/pagopa/microservice/config/OpenApiConfig.java b/src/main/java/it/gov/pagopa/microservice/config/OpenApiConfig.java deleted file mode 100644 index 6b7ec18..0000000 --- a/src/main/java/it/gov/pagopa/microservice/config/OpenApiConfig.java +++ /dev/null @@ -1,129 +0,0 @@ -package it.gov.pagopa.microservice.config; - -import static it.gov.pagopa.microservice.util.Constants.HEADER_REQUEST_ID; - -import io.swagger.v3.oas.models.Components; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.Paths; -import io.swagger.v3.oas.models.headers.Header; -import io.swagger.v3.oas.models.info.Info; -import io.swagger.v3.oas.models.media.StringSchema; -import io.swagger.v3.oas.models.parameters.Parameter; -import io.swagger.v3.oas.models.responses.ApiResponses; -import io.swagger.v3.oas.models.security.SecurityScheme; -import java.util.Collections; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import org.springdoc.core.customizers.OpenApiCustomiser; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class OpenApiConfig { - - @Bean - public OpenAPI customOpenAPI( - @Value("${info.application.artifactId}") String appName, - @Value("${info.application.description}") String appDescription, - @Value("${info.application.version}") String appVersion) { - return new OpenAPI() - .components( - new Components() - .addSecuritySchemes( - "ApiKey", - new SecurityScheme() - .type(SecurityScheme.Type.APIKEY) - .description("The API key to access this function app.") - .name("Ocp-Apim-Subscription-Key") - .in(SecurityScheme.In.HEADER))) - .info( - new Info() - .title(appName) - .version(appVersion) - .description(appDescription) - .termsOfService("https://www.pagopa.gov.it/")); - } - - @Bean - public OpenApiCustomiser sortOperationsAlphabetically() { - return openApi -> { - Paths paths = - openApi - .getPaths() - .entrySet() - .stream() - .sorted(Map.Entry.comparingByKey()) - .collect( - Paths::new, - (map, item) -> map.addPathItem(item.getKey(), item.getValue()), - Paths::putAll); - - paths.forEach( - (key, value) -> - value - .readOperations() - .forEach( - operation -> { - var responses = - operation - .getResponses() - .entrySet() - .stream() - .sorted(Map.Entry.comparingByKey()) - .collect( - ApiResponses::new, - (map, item) -> - map.addApiResponse(item.getKey(), item.getValue()), - ApiResponses::putAll); - operation.setResponses(responses); - })); - openApi.setPaths(paths); - }; - } - - @Bean - public OpenApiCustomiser addCommonHeaders() { - return openApi -> - openApi - .getPaths() - .forEach( - (key, value) -> { - - // add Request-ID as request header - var header = - Optional.ofNullable(value.getParameters()) - .orElse(Collections.emptyList()) - .parallelStream() - .filter(Objects::nonNull) - .anyMatch(elem -> HEADER_REQUEST_ID.equals(elem.getName())); - if (!header) { - value.addParametersItem( - new Parameter() - .in("header") - .name(HEADER_REQUEST_ID) - .schema(new StringSchema()) - .description( - "This header identifies the call, if not passed it is self-generated. This ID is returned in the response.")); - } - - // add Request-ID as response header - value - .readOperations() - .forEach( - operation -> - operation - .getResponses() - .values() - .forEach( - response -> - response.addHeaderObject( - HEADER_REQUEST_ID, - new Header() - .schema(new StringSchema()) - .description( - "This header identifies the call")))); - }); - } -} diff --git a/src/main/java/it/gov/pagopa/microservice/config/RequestFilter.java b/src/main/java/it/gov/pagopa/microservice/config/RequestFilter.java deleted file mode 100644 index 63726e3..0000000 --- a/src/main/java/it/gov/pagopa/microservice/config/RequestFilter.java +++ /dev/null @@ -1,58 +0,0 @@ -package it.gov.pagopa.microservice.config; - -import static it.gov.pagopa.microservice.util.Constants.HEADER_REQUEST_ID; - -import java.io.IOException; -import java.util.UUID; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.slf4j.MDC; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; - -@Component -@Order(Ordered.HIGHEST_PRECEDENCE) -@Slf4j -public class RequestFilter implements Filter { - - /** - * Get the request ID from the custom header "X-Request-Id" if present, otherwise it generates - * one. Set the X-Request-Id value in the {@code response} and in the MDC - * - * @param request http request - * @param response http response - * @param chain next filter - * @throws IOException if an I/O error occurs during this filter's processing of the request - * @throws ServletException if the processing fails for any other reason - */ - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { - try { - HttpServletRequest httRequest = (HttpServletRequest) request; - - // get requestId from header or generate one - String requestId = httRequest.getHeader(HEADER_REQUEST_ID); - if (requestId == null || requestId.isEmpty()) { - requestId = UUID.randomUUID().toString(); - } - - // set requestId in MDC - MDC.put("requestId", requestId); - - // set requestId in the response header - ((HttpServletResponse) response).setHeader(HEADER_REQUEST_ID, requestId); - chain.doFilter(request, response); - } finally { - MDC.clear(); - } - } - -} diff --git a/src/main/java/it/gov/pagopa/microservice/config/ResponseValidator.java b/src/main/java/it/gov/pagopa/microservice/config/ResponseValidator.java deleted file mode 100644 index 67cc3af..0000000 --- a/src/main/java/it/gov/pagopa/microservice/config/ResponseValidator.java +++ /dev/null @@ -1,52 +0,0 @@ -package it.gov.pagopa.microservice.config; - -import it.gov.pagopa.microservice.exception.AppException; -import java.util.Set; -import javax.validation.ConstraintViolation; -import javax.validation.Validator; -import org.apache.commons.lang3.StringUtils; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.annotation.AfterReturning; -import org.aspectj.lang.annotation.Aspect; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Component; - -@Aspect -@Component -public class ResponseValidator { - - @Autowired - private Validator validator; - - - /** - * This method validates the response annotated with the {@link javax.validation.constraints} - * - * @param joinPoint not used - * @param result the response to validate - */ - // TODO: set your package - @AfterReturning(pointcut = "execution(* it.gov.pagopa.microservice.controller.*.*(..))", returning = "result") - public void validateResponse(JoinPoint joinPoint, Object result) { - if (result instanceof ResponseEntity) { - validateResponse((ResponseEntity) result); - } - } - - private void validateResponse(ResponseEntity response) { - if (response.getBody() != null) { - Set> validationResults = validator.validate(response.getBody()); - - if (!validationResults.isEmpty()) { - var sb = new StringBuilder(); - for (ConstraintViolation error : validationResults) { - sb.append(error.getPropertyPath()).append(" ").append(error.getMessage()).append(". "); - } - var msg = StringUtils.chop(sb.toString()); - throw new AppException(HttpStatus.INTERNAL_SERVER_ERROR, "Invalid response", msg); - } - } - } -} diff --git a/src/main/java/it/gov/pagopa/microservice/config/WebMvcConfiguration.java b/src/main/java/it/gov/pagopa/microservice/config/WebMvcConfiguration.java deleted file mode 100644 index c61db33..0000000 --- a/src/main/java/it/gov/pagopa/microservice/config/WebMvcConfiguration.java +++ /dev/null @@ -1,30 +0,0 @@ -package it.gov.pagopa.microservice.config; - -import com.fasterxml.jackson.databind.ObjectMapper; -import it.gov.pagopa.microservice.model.AppCorsConfiguration; -import lombok.SneakyThrows; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.CorsRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - - -@Configuration -public class WebMvcConfiguration implements WebMvcConfigurer { - - @Value("${cors.configuration}") - private String corsConfiguration; - - - @SneakyThrows - @Override - public void addCorsMappings(CorsRegistry registry) { - AppCorsConfiguration appCorsConfiguration = new ObjectMapper().readValue(corsConfiguration, - AppCorsConfiguration.class); - registry.addMapping("/**") - .allowedOrigins(appCorsConfiguration.getOrigins()) - .allowedMethods(appCorsConfiguration.getMethods()); - } -} - - diff --git a/src/main/java/it/gov/pagopa/microservice/exception/AppError.java b/src/main/java/it/gov/pagopa/microservice/exception/AppError.java deleted file mode 100644 index d9ccb08..0000000 --- a/src/main/java/it/gov/pagopa/microservice/exception/AppError.java +++ /dev/null @@ -1,30 +0,0 @@ -package it.gov.pagopa.microservice.exception; - -import lombok.Getter; -import org.springframework.http.HttpStatus; - - -@Getter -public enum AppError { - INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "Internal Server Error", "Something was wrong"), - BAD_REQUEST(HttpStatus.INTERNAL_SERVER_ERROR, "Bad Request", "%s"), - UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "Unauthorized", "Error during authentication"), - FORBIDDEN(HttpStatus.FORBIDDEN, "Forbidden", "This method is forbidden"), - RESPONSE_NOT_READABLE(HttpStatus.BAD_GATEWAY, "Response Not Readable", "The response body is not readable"), - - UNKNOWN(null, null, null); - - - public final HttpStatus httpStatus; - public final String title; - public final String details; - - - AppError(HttpStatus httpStatus, String title, String details) { - this.httpStatus = httpStatus; - this.title = title; - this.details = details; - } -} - - diff --git a/src/main/java/it/gov/pagopa/microservice/exception/AppException.java b/src/main/java/it/gov/pagopa/microservice/exception/AppException.java deleted file mode 100644 index e16fd36..0000000 --- a/src/main/java/it/gov/pagopa/microservice/exception/AppException.java +++ /dev/null @@ -1,87 +0,0 @@ -package it.gov.pagopa.microservice.exception; - -import java.util.Formatter; -import javax.validation.constraints.NotNull; -import lombok.EqualsAndHashCode; -import lombok.Value; -import org.springframework.http.HttpStatus; -import org.springframework.validation.annotation.Validated; - -/** - * Custom exception. - *

See {@link ErrorHandler} - */ -@EqualsAndHashCode(callSuper = true) -@Value -@Validated -public class AppException extends RuntimeException { - - /** - * title returned to the response when this exception occurred - */ - String title; - - /** - * http status returned to the response when this exception occurred - */ - HttpStatus httpStatus; - - /** - * @param httpStatus HTTP status returned to the response - * @param title title returned to the response when this exception occurred - * @param message the detail message returend to the response - * @param cause The cause of this {@link AppException} - */ - public AppException(@NotNull HttpStatus httpStatus, @NotNull String title, - @NotNull String message, Throwable cause) { - super(message, cause); - this.title = title; - this.httpStatus = httpStatus; - } - - /** - * @param httpStatus HTTP status returned to the response - * @param title title returned to the response when this exception occurred - * @param message the detail message returend to the response - */ - public AppException(@NotNull HttpStatus httpStatus, @NotNull String title, @NotNull String message) { - super(message); - this.title = title; - this.httpStatus = httpStatus; - } - - - /** - * @param appError Response template returned to the response - * @param args {@link Formatter} replaces the placeholders in "details" string of - * {@link AppError} with the arguments. If there are more arguments than format - * specifiers, the extra arguments are ignored. - */ - public AppException(@NotNull AppError appError, Object... args) { - super(formatDetails(appError, args)); - this.httpStatus = appError.httpStatus; - this.title = appError.title; - } - - /** - * @param appError Response template returned to the response - * @param cause The cause of this {@link AppException} - * @param args Arguments for the details of {@link AppError} replaced by the - * {@link Formatter}. If there are more arguments than format specifiers, the - * extra arguments are ignored. - */ - public AppException(@NotNull AppError appError, Throwable cause, Object... args) { - super(formatDetails(appError, args), cause); - this.httpStatus = appError.httpStatus; - this.title = appError.title; - } - - private static String formatDetails(AppError appError, Object[] args) { - return String.format(appError.details, args); - } - - @Override - public String toString() { - return "AppException(" + httpStatus + ", " + title + ")" + super.toString(); - } -} diff --git a/src/main/java/it/gov/pagopa/microservice/exception/ErrorHandler.java b/src/main/java/it/gov/pagopa/microservice/exception/ErrorHandler.java deleted file mode 100644 index 3fd7e49..0000000 --- a/src/main/java/it/gov/pagopa/microservice/exception/ErrorHandler.java +++ /dev/null @@ -1,220 +0,0 @@ -package it.gov.pagopa.microservice.exception; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import feign.FeignException; -import it.gov.pagopa.microservice.model.ProblemJson; -import java.util.ArrayList; -import java.util.List; -import lombok.extern.slf4j.Slf4j; -import org.hibernate.exception.ConstraintViolationException; -import org.springframework.beans.TypeMismatchException; -import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.http.converter.HttpMessageNotReadableException; -import org.springframework.validation.FieldError; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.MissingServletRequestParameterException; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.context.request.WebRequest; -import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; -import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; - -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; - -/** - * All Exceptions are handled by this class - */ -@ControllerAdvice -@Slf4j -public class ErrorHandler extends ResponseEntityExceptionHandler { - - /** - * Handle if the input request is not a valid JSON - * - * @param ex {@link HttpMessageNotReadableException} exception raised - * @param headers of the response - * @param status of the response - * @param request from frontend - * @return a {@link ProblemJson} as response with the cause and with a 400 as HTTP status - */ - @Override - public ResponseEntity handleHttpMessageNotReadable(HttpMessageNotReadableException ex, - HttpHeaders headers, HttpStatus status, WebRequest request) { - log.warn("Input not readable: ", ex); - var errorResponse = ProblemJson.builder() - .status(HttpStatus.BAD_REQUEST.value()) - .title(AppError.BAD_REQUEST.getTitle()) - .detail("Invalid input format") - .build(); - return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); - } - - /** - * Handle if missing some request parameters in the request - * - * @param ex {@link MissingServletRequestParameterException} exception raised - * @param headers of the response - * @param status of the response - * @param request from frontend - * @return a {@link ProblemJson} as response with the cause and with a 400 as HTTP status - */ - @Override - public ResponseEntity handleMissingServletRequestParameter( - MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatus status, - WebRequest request) { - log.warn("Missing request parameter: ", ex); - var errorResponse = ProblemJson.builder() - .status(HttpStatus.BAD_REQUEST.value()) - .title(AppError.BAD_REQUEST.getTitle()) - .detail(ex.getMessage()) - .build(); - return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); - } - - - /** - * Customize the response for TypeMismatchException. - * - * @param ex the exception - * @param headers the headers to be written to the response - * @param status the selected response status - * @param request the current request - * @return a {@code ResponseEntity} instance - */ - @Override - protected ResponseEntity handleTypeMismatch(TypeMismatchException ex, HttpHeaders headers, - HttpStatus status, WebRequest request) { - log.warn("Type mismatch: ", ex); - var errorResponse = ProblemJson.builder() - .status(HttpStatus.BAD_REQUEST.value()) - .title(AppError.BAD_REQUEST.getTitle()) - .detail(String.format("Invalid value %s for property %s", ex.getValue(), - ((MethodArgumentTypeMismatchException) ex).getName())) - .build(); - return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); - } - - /** - * Handle if validation constraints are unsatisfied - * - * @param ex {@link MethodArgumentNotValidException} exception raised - * @param headers of the response - * @param status of the response - * @param request from frontend - * @return a {@link ProblemJson} as response with the cause and with a 400 as HTTP status - */ - @Override - protected ResponseEntity handleMethodArgumentNotValid(MethodArgumentNotValidException ex, - HttpHeaders headers, HttpStatus status, WebRequest request) { - List details = new ArrayList<>(); - for (FieldError error : ex.getBindingResult().getFieldErrors()) { - details.add(error.getField() + ": " + error.getDefaultMessage()); - } - var detailsMessage = String.join(", ", details); - log.warn("Input not valid: " + detailsMessage); - var errorResponse = ProblemJson.builder() - .status(HttpStatus.BAD_REQUEST.value()) - .title(AppError.BAD_REQUEST.getTitle()) - .detail(detailsMessage) - .build(); - return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); - } - - @ExceptionHandler({javax.validation.ConstraintViolationException.class}) - public ResponseEntity handleConstraintViolationException( - final javax.validation.ConstraintViolationException ex, final WebRequest request) { - log.warn("Validation Error raised:", ex); - var errorResponse = ProblemJson.builder() - .status(HttpStatus.BAD_REQUEST.value()) - .title(AppError.BAD_REQUEST.getTitle()) - .detail(ex.getMessage()) - .build(); - return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); - } - - - /** - * Handle if a {@link FeignException} is raised - * - * @param ex {@link FeignException} exception raised - * @param request from frontend - * @return a {@link ProblemJson} as response with the cause and with an appropriated HTTP status - */ - @ExceptionHandler({FeignException.class}) - public ResponseEntity handleFeignException(final FeignException ex, final WebRequest request) { - log.warn("FeignException raised: ", ex); - - ProblemJson problem; - if(ex.responseBody().isPresent()) { - var body = new String(ex.responseBody().get().array(), StandardCharsets.UTF_8); - try { - problem = new ObjectMapper().readValue(body, ProblemJson.class); - } catch (JsonProcessingException e) { - problem = ProblemJson.builder() - .status(HttpStatus.BAD_GATEWAY.value()) - .title(AppError.RESPONSE_NOT_READABLE.getTitle()) - .detail(AppError.RESPONSE_NOT_READABLE.getDetails()) - .build(); - } - } else { - problem = ProblemJson.builder() - .status(HttpStatus.BAD_GATEWAY.value()) - .title("No Response Body") - .detail("Error with external dependency") - .build(); - } - - return new ResponseEntity<>(problem, HttpStatus.valueOf(problem.getStatus())); - } - - - /** - * Handle if a {@link AppException} is raised - * - * @param ex {@link AppException} exception raised - * @param request from frontend - * @return a {@link ProblemJson} as response with the cause and with an appropriated HTTP status - */ - @ExceptionHandler({AppException.class}) - public ResponseEntity handleAppException(final AppException ex, - final WebRequest request) { - if (ex.getCause() != null) { - log.warn("App Exception raised: " + ex.getMessage() + "\nCause of the App Exception: ", - ex.getCause()); - } else { - log.warn("App Exception raised: ", ex); - } - var errorResponse = ProblemJson.builder() - .status(ex.getHttpStatus().value()) - .title(ex.getTitle()) - .detail(ex.getMessage()) - .build(); - return new ResponseEntity<>(errorResponse, ex.getHttpStatus()); - } - - - /** - * Handle if a {@link Exception} is raised - * - * @param ex {@link Exception} exception raised - * @param request from frontend - * @return a {@link ProblemJson} as response with the cause and with 500 as HTTP status - */ - @ExceptionHandler({Exception.class}) - public ResponseEntity handleGenericException(final Exception ex, - final WebRequest request) { - log.error("Generic Exception raised:", ex); - var errorResponse = ProblemJson.builder() - .status(HttpStatus.INTERNAL_SERVER_ERROR.value()) - .title(AppError.INTERNAL_SERVER_ERROR.getTitle()) - .detail(ex.getMessage()) - .build(); - return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR); - } -} diff --git a/src/main/java/it/gov/pagopa/microservice/model/ProblemJson.java b/src/main/java/it/gov/pagopa/microservice/model/ProblemJson.java deleted file mode 100644 index db11a37..0000000 --- a/src/main/java/it/gov/pagopa/microservice/model/ProblemJson.java +++ /dev/null @@ -1,40 +0,0 @@ -package it.gov.pagopa.microservice.model; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.v3.oas.annotations.media.Schema; -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.ToString; - -/** - * Object returned as response in case of an error. - *

See {@link it.pagopa.microservice.exception.ErrorHandler} - */ -@Data -@Builder(toBuilder = true) -@NoArgsConstructor -@AllArgsConstructor -@ToString -@JsonIgnoreProperties(ignoreUnknown = true) -public class ProblemJson { - - @JsonProperty("title") - @Schema(description = "A short, summary of the problem type. Written in english and readable for engineers (usually not suited for non technical stakeholders and not localized); example: Service Unavailable") - private String title; - - @JsonProperty("status") - @Schema(example = "200", description = "The HTTP status code generated by the origin server for this occurrence of the problem.") - @Min(100) - @Max(600) - private Integer status; - - @JsonProperty("detail") - @Schema(example = "There was an error processing the request", description = "A human readable explanation specific to this occurrence of the problem.") - private String detail; - -} diff --git a/src/main/java/it/gov/pagopa/microservice/util/Constants.java b/src/main/java/it/gov/pagopa/microservice/util/Constants.java deleted file mode 100644 index e5812c7..0000000 --- a/src/main/java/it/gov/pagopa/microservice/util/Constants.java +++ /dev/null @@ -1,11 +0,0 @@ -package it.gov.pagopa.microservice.util; - -import lombok.experimental.UtilityClass; - -@UtilityClass -public class Constants { - - - public static final String HEADER_REQUEST_ID = "X-Request-Id"; - -} diff --git a/src/test/java/it/gov/pagopa/microservice/ApplicationTest.java b/src/test/java/it/gov/pagopa/microservice/ApplicationTest.java index 80c6e10..56dcf59 100644 --- a/src/test/java/it/gov/pagopa/microservice/ApplicationTest.java +++ b/src/test/java/it/gov/pagopa/microservice/ApplicationTest.java @@ -1,16 +1,16 @@ package it.gov.pagopa.microservice; -import static org.junit.jupiter.api.Assertions.assertTrue; - import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; +import static org.junit.jupiter.api.Assertions.assertTrue; + @SpringBootTest class ApplicationTest { - @Test - void contextLoads() { - // check only if the context is loaded - assertTrue(true); - } + @Test + void contextLoads() { + // check only if the context is loaded + assertTrue(true); + } } diff --git a/src/test/java/it/gov/pagopa/microservice/OpenApiGenerationTest.java b/src/test/java/it/gov/pagopa/microservice/OpenApiGenerationTest.java index 07f521b..f546ae8 100644 --- a/src/test/java/it/gov/pagopa/microservice/OpenApiGenerationTest.java +++ b/src/test/java/it/gov/pagopa/microservice/OpenApiGenerationTest.java @@ -1,12 +1,7 @@ package it.gov.pagopa.microservice; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; - import com.fasterxml.jackson.databind.ObjectMapper; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; +import it.gov.pagopa.mdb.gps.service.Application; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -16,32 +11,41 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; + @SpringBootTest(classes = Application.class) @AutoConfigureMockMvc class OpenApiGenerationTest { - @Autowired ObjectMapper objectMapper; + @Autowired + ObjectMapper objectMapper; - @Autowired private MockMvc mvc; + @Autowired + private MockMvc mvc; - @Test - void swaggerSpringPlugin() throws Exception { - mvc.perform(MockMvcRequestBuilders.get("/v3/api-docs").accept(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()) - .andDo( - (result) -> { - assertNotNull(result); - assertNotNull(result.getResponse()); - final String content = result.getResponse().getContentAsString(); - assertFalse(content.isBlank()); - assertFalse(content.contains("${"), "Generated swagger contains placeholders"); - Object swagger = - objectMapper.readValue(result.getResponse().getContentAsString(), Object.class); - String formatted = - objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(swagger); - Path basePath = Paths.get("openapi/"); - Files.createDirectories(basePath); - Files.write(basePath.resolve("openapi.json"), formatted.getBytes()); - }); - } + @Test + void swaggerSpringPlugin() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/v3/api-docs").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()) + .andDo( + (result) -> { + assertNotNull(result); + assertNotNull(result.getResponse()); + final String content = result.getResponse().getContentAsString(); + assertFalse(content.isBlank()); + assertFalse(content.contains("${"), "Generated swagger contains placeholders"); + Object swagger = + objectMapper.readValue(result.getResponse().getContentAsString(), Object.class); + String formatted = + objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(swagger); + Path basePath = Paths.get("openapi/"); + Files.createDirectories(basePath); + Files.write(basePath.resolve("openapi.json"), formatted.getBytes()); + }); + } } From 7d33334ff5f768087400d30eb5033d643a0253cb Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 28 Nov 2024 15:21:46 +0100 Subject: [PATCH 02/29] [PPANTT-191] added health and mdb endpoint and defined mdb models and mapper. Bump spring doc dependency version --- pom.xml | 2 +- .../mdb/gps/service/config/LoggingAspect.java | 1 - .../service/config/MappingsConfiguration.java | 7 ++- .../service/controller/HomeController.java | 28 +++++++++ .../service/controller/MdbGpsController.java | 57 +++++++++++++++++++ ...tionRequestToMdbPaymentOptionResponse.java | 57 +++++++++++++++++++ .../model/MdbPaymentOptionRequest.java | 19 +++++++ .../MdbPaymentOptionRequestProperties.java | 46 +++++++++++++++ .../model/MdbPaymentOptionResponse.java | 21 +++++++ .../mdb/gps/service/model/PaymentOption.java | 54 ++++++++++++++++++ .../pagopa/mdb/gps/service/model/Stamp.java | 35 ++++++++++++ .../mdb/gps/service/model/Transfer.java | 39 +++++++++++++ 12 files changed, 363 insertions(+), 3 deletions(-) create mode 100644 src/main/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsController.java create mode 100644 src/main/java/it/gov/pagopa/mdb/gps/service/mapper/ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse.java create mode 100644 src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionRequest.java create mode 100644 src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionRequestProperties.java create mode 100644 src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionResponse.java create mode 100644 src/main/java/it/gov/pagopa/mdb/gps/service/model/PaymentOption.java create mode 100644 src/main/java/it/gov/pagopa/mdb/gps/service/model/Stamp.java create mode 100644 src/main/java/it/gov/pagopa/mdb/gps/service/model/Transfer.java diff --git a/pom.xml b/pom.xml index 460d4b4..3ce9b2f 100644 --- a/pom.xml +++ b/pom.xml @@ -75,7 +75,7 @@ org.springdoc springdoc-openapi-ui - 1.6.11 + 1.8.0 diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/config/LoggingAspect.java b/src/main/java/it/gov/pagopa/mdb/gps/service/config/LoggingAspect.java index f923caf..8a6cac3 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/config/LoggingAspect.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/config/LoggingAspect.java @@ -25,7 +25,6 @@ import static it.gov.pagopa.mdb.gps.service.util.CommonUtility.deNull; - @Aspect @Component @Slf4j diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/config/MappingsConfiguration.java b/src/main/java/it/gov/pagopa/mdb/gps/service/config/MappingsConfiguration.java index d5e0159..d328e6e 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/config/MappingsConfiguration.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/config/MappingsConfiguration.java @@ -1,6 +1,9 @@ package it.gov.pagopa.mdb.gps.service.config; +import it.gov.pagopa.mdb.gps.service.mapper.ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse; +import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionRequest; +import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionResponse; import org.modelmapper.ModelMapper; import org.modelmapper.convention.MatchingStrategies; import org.springframework.context.annotation.Bean; @@ -13,7 +16,9 @@ public class MappingsConfiguration { ModelMapper modelMapper() { ModelMapper mapper = new ModelMapper(); mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); + + mapper.createTypeMap(MdbPaymentOptionRequest.class, MdbPaymentOptionResponse.class) + .setConverter(new ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse()); return mapper; } - } diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/controller/HomeController.java b/src/main/java/it/gov/pagopa/mdb/gps/service/controller/HomeController.java index 7d96f77..bc636e3 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/controller/HomeController.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/controller/HomeController.java @@ -1,9 +1,15 @@ package it.gov.pagopa.mdb.gps.service.controller; import io.swagger.v3.oas.annotations.Hidden; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import it.gov.pagopa.mdb.gps.service.model.AppInfo; import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.view.RedirectView; @@ -14,6 +20,14 @@ public class HomeController { @Value("${server.servlet.context-path}") String basePath; + @Value("${info.application.name}") + private String name; + + @Value("${info.application.version}") + private String version; + + @Value("${info.properties.environment}") + private String environment; /** * @return redirect to Swagger page documentation @@ -26,4 +40,18 @@ public RedirectView home() { } return new RedirectView(basePath + "swagger-ui.html"); } + + + @Operation( + summary = "health check", + description = "Return OK if application is started", + security = {@SecurityRequirement(name = "ApiKey")}, + tags = {"Home"}) + @GetMapping(value = "/info") + @ResponseStatus(HttpStatus.OK) + public ResponseEntity healthCheck() { + // Used just for health checking + AppInfo info = AppInfo.builder().name(name).version(version).environment(environment).build(); + return ResponseEntity.status(HttpStatus.OK).body(info); + } } diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsController.java b/src/main/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsController.java new file mode 100644 index 0000000..49fd7ab --- /dev/null +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsController.java @@ -0,0 +1,57 @@ +package it.gov.pagopa.mdb.gps.service.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionRequest; +import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionResponse; +import it.gov.pagopa.mdb.gps.service.model.ProblemJson; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import org.modelmapper.ModelMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +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.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping(value = "/mbd/paymentOption", produces = MediaType.APPLICATION_JSON_VALUE) +@Tag(name = "MDB GPS") +public class MdbGpsController { + + private final ModelMapper modelMapper; + + @Autowired + public MdbGpsController(ModelMapper modelMapper) { + this.modelMapper = modelMapper; + } + + @PostMapping("") + @ResponseStatus(HttpStatus.OK) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = MdbPaymentOptionResponse.class))), + @ApiResponse(responseCode = "400", description = "Bad Request", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ProblemJson.class))), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(schema = @Schema())), + @ApiResponse(responseCode = "404", description = "Not found", content = @Content(schema = @Schema(implementation = ProblemJson.class))), + @ApiResponse(responseCode = "429", description = "Too many requests", content = @Content(schema = @Schema())), + @ApiResponse(responseCode = "500", description = "Service unavailable", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ProblemJson.class))) + }) + @Operation(summary = "Create MDB payment option", security = {@SecurityRequirement(name = "ApiKey")}) + public @Valid MdbPaymentOptionResponse createMdbPaymentOption( + @RequestBody @NotNull @Valid MdbPaymentOptionRequest ciBundleAttributes + ) { + return this.modelMapper.map(ciBundleAttributes, MdbPaymentOptionResponse.class); + } +} \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/mapper/ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse.java b/src/main/java/it/gov/pagopa/mdb/gps/service/mapper/ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse.java new file mode 100644 index 0000000..97b42f0 --- /dev/null +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/mapper/ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse.java @@ -0,0 +1,57 @@ +package it.gov.pagopa.mdb.gps.service.mapper; + +import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionRequest; +import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionRequestProperties; +import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionResponse; +import it.gov.pagopa.mdb.gps.service.model.PaymentOption; +import it.gov.pagopa.mdb.gps.service.model.Stamp; +import it.gov.pagopa.mdb.gps.service.model.Transfer; +import org.modelmapper.Converter; +import org.modelmapper.spi.MappingContext; + +import java.time.LocalDateTime; +import java.util.Collections; + +/** + * Converter class that specify how to convert a {@link MdbPaymentOptionRequest} instance to a {@link MdbPaymentOptionResponse} instance + */ +public class ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse implements Converter { + + private static final boolean IS_PARTIAL_PAYMENT = false; + private static final String ID_TRANSFER = "1"; + private static final String REMITTANCE_INFORMATION = "Pagamento MDB"; + private static final String STAMP_TYPE = "st"; + + @Override + public MdbPaymentOptionResponse convert(MappingContext context) { + MdbPaymentOptionRequestProperties model = context.getSource().getProperties(); + + Transfer transfer = Transfer.builder() + .amount(model.getAmount()) + .idTransfer(ID_TRANSFER) + .organizationFiscalCode(model.getFiscalCode()) + .remittanceInformation(REMITTANCE_INFORMATION) + .stamp(Stamp.builder() + .hashDocument(model.getDocumentHash()) + .provincialResidence(model.getProvincialResidence()) + .stampType(STAMP_TYPE) + .build()) + .build(); + + LocalDateTime now = LocalDateTime.now(); + PaymentOption paymentOption = PaymentOption.builder() + .firstName(model.getFirstName()) + .lastName(model.getLastName()) + .amount(model.getAmount()) + .description(model.getDescription()) + .dueDate(now) + .retentionDate(now) + .isPartialPayment(IS_PARTIAL_PAYMENT) + .transfer(Collections.singletonList(transfer)) + .build(); + + return MdbPaymentOptionResponse.builder() + .paymentOption(Collections.singletonList(paymentOption)) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionRequest.java b/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionRequest.java new file mode 100644 index 0000000..36c84f1 --- /dev/null +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionRequest.java @@ -0,0 +1,19 @@ +package it.gov.pagopa.mdb.gps.service.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class MdbPaymentOptionRequest { + + @Valid + @Schema(description = "MDB payment option's properties", requiredMode = Schema.RequiredMode.REQUIRED) + private MdbPaymentOptionRequestProperties properties; +} \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionRequestProperties.java b/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionRequestProperties.java new file mode 100644 index 0000000..4277a4c --- /dev/null +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionRequestProperties.java @@ -0,0 +1,46 @@ +package it.gov.pagopa.mdb.gps.service.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MdbPaymentOptionRequestProperties { + + @NotNull(message = "amount is required") + @Schema(description = "MDB amount", requiredMode = Schema.RequiredMode.REQUIRED) + private Long amount; + + @NotBlank + @Schema(description = "Description", requiredMode = Schema.RequiredMode.REQUIRED) + private String description; + + @NotBlank + @Schema(description = "Debtor's name", requiredMode = Schema.RequiredMode.REQUIRED) + private String firstName; + + @NotBlank + @Schema(description = "Debtor's last name", requiredMode = Schema.RequiredMode.REQUIRED) + private String lastName; + + @NotBlank + @Schema(description = "Debtor's fiscal code", requiredMode = Schema.RequiredMode.REQUIRED) + private String fiscalCode; + + @NotBlank + @Schema(description = "Debtor's residence province", requiredMode = Schema.RequiredMode.REQUIRED) + private String provincialResidence; + + @NotBlank + @Size(min = 44, max = 44) + @Schema(description = "MDB document's hash", requiredMode = Schema.RequiredMode.REQUIRED) + private String documentHash; +} \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionResponse.java b/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionResponse.java new file mode 100644 index 0000000..a8a47c2 --- /dev/null +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionResponse.java @@ -0,0 +1,21 @@ +package it.gov.pagopa.mdb.gps.service.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class MdbPaymentOptionResponse { + + @Valid + @Schema(description = "MDB payment option", requiredMode = Schema.RequiredMode.REQUIRED) + private List<@Valid PaymentOption> paymentOption; +} \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/model/PaymentOption.java b/src/main/java/it/gov/pagopa/mdb/gps/service/model/PaymentOption.java new file mode 100644 index 0000000..7e68a7c --- /dev/null +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/model/PaymentOption.java @@ -0,0 +1,54 @@ +package it.gov.pagopa.mdb.gps.service.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PaymentOption { + + @NotBlank + @Schema(description = "Debtor's name", requiredMode = Schema.RequiredMode.REQUIRED) + private String firstName; + + @NotBlank + @Schema(description = "Debtor's last name", requiredMode = Schema.RequiredMode.REQUIRED) + private String lastName; + + @NotNull(message = "amount is required") + @Schema(description = "Payment option's amount", requiredMode = Schema.RequiredMode.REQUIRED) + private Long amount; + + @NotBlank(message = "payment option description is required") + @Size(max = 140) // compliant to paForNode.xsd + @Schema(description = "Payment option's description", requiredMode = Schema.RequiredMode.REQUIRED) + private String description; + + @NotNull(message = "is partial payment is required") + @Schema(description = "Payment option's is partial payment flag", requiredMode = Schema.RequiredMode.REQUIRED) + private Boolean isPartialPayment; + + @NotNull(message = "due date is required") + @Schema(description = "Payment option's due date", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime dueDate; + + @Schema(description = "Payment option's retention date", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime retentionDate; + + @Valid + @Schema(description = "Payment option's transfer list", requiredMode = Schema.RequiredMode.REQUIRED) + private List<@Valid Transfer> transfer = new ArrayList<>(); +} \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/model/Stamp.java b/src/main/java/it/gov/pagopa/mdb/gps/service/model/Stamp.java new file mode 100644 index 0000000..46085d5 --- /dev/null +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/model/Stamp.java @@ -0,0 +1,35 @@ +package it.gov.pagopa.mdb.gps.service.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Stamp { + + @NotBlank + @Size(max = 72) + @Schema(description = "Document hash type is stBase64Binary72 as described in https://github.com/pagopa/pagopa-api.", requiredMode = Schema.RequiredMode.REQUIRED) + // Stamp generally get as input a base64sha256, that is the SHA256 hash of a given string encoded with Base64. + // It is not equivalent to base64encode(sha256(“test”)), if sha256() returns a hexadecimal representation. + // The result should normally be 44 characters, to be compliant with as-is it was extended to 72 + private String hashDocument; + + @NotBlank + @Size(min = 2, max = 2) + @Schema(description = "The type of the stamp", minLength = 2, maxLength = 2, requiredMode = Schema.RequiredMode.REQUIRED) + private String stampType; + + @NotBlank + @Pattern(regexp = "[A-Z]{2}") + @Schema(description = "The province of residence", example = "RM", pattern = "[A-Z]{2,2}", requiredMode = Schema.RequiredMode.REQUIRED) + private String provincialResidence; +} \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/model/Transfer.java b/src/main/java/it/gov/pagopa/mdb/gps/service/model/Transfer.java new file mode 100644 index 0000000..9ea7432 --- /dev/null +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/model/Transfer.java @@ -0,0 +1,39 @@ +package it.gov.pagopa.mdb.gps.service.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Transfer { + + @NotBlank(message = "id transfer is required") + @Schema(description = "Transfer's id", allowableValues = {"1", "2", "3", "4", "5"}, requiredMode = Schema.RequiredMode.REQUIRED) + private String idTransfer; + + @NotNull(message = "amount is required") + @Schema(description = "Transfer's amount", requiredMode = Schema.RequiredMode.REQUIRED) + private Long amount; + + @Schema(description = "Fiscal code related to the organization targeted by this transfer.", example = "00000000000") + private String organizationFiscalCode; + + @NotBlank(message = "remittance information is required") + @Size(max = 140, message = "remittance information must be compliant to EACT FORMATTING RULES, up to 140 chars") + @Schema(description = "Transfer's remittance information", requiredMode = Schema.RequiredMode.REQUIRED) + // https://docs.pagopa.it/saci/specifiche-attuative-dei-codici-identificativi-di-versamento-riversamento-e-rendicontazione/operazione-di-trasferimento-fondi + private String remittanceInformation; // causale + + @Valid + @Schema(description = "Transfer's stamp", requiredMode = Schema.RequiredMode.REQUIRED) + private Stamp stamp; +} \ No newline at end of file From 085ca31956dd81ef82e2cb2d5198aaaa8941c3c1 Mon Sep 17 00:00:00 2001 From: giomella Date: Thu, 28 Nov 2024 15:32:07 +0100 Subject: [PATCH 03/29] [PPANTT-191] added javadoc --- .../mdb/gps/service/controller/HomeController.java | 7 +++++-- .../mdb/gps/service/controller/MdbGpsController.java | 10 ++++++++-- .../mdb/gps/service/model/MdbPaymentOptionRequest.java | 3 +++ .../model/MdbPaymentOptionRequestProperties.java | 3 +++ .../gps/service/model/MdbPaymentOptionResponse.java | 3 +++ .../pagopa/mdb/gps/service/model/PaymentOption.java | 3 +++ .../it/gov/pagopa/mdb/gps/service/model/Stamp.java | 3 +++ .../it/gov/pagopa/mdb/gps/service/model/Transfer.java | 3 +++ 8 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/controller/HomeController.java b/src/main/java/it/gov/pagopa/mdb/gps/service/controller/HomeController.java index bc636e3..83d9f27 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/controller/HomeController.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/controller/HomeController.java @@ -41,7 +41,11 @@ public RedirectView home() { return new RedirectView(basePath + "swagger-ui.html"); } - + /** + * Return app name, version and environment + * + * @return the app info + */ @Operation( summary = "health check", description = "Return OK if application is started", @@ -50,7 +54,6 @@ public RedirectView home() { @GetMapping(value = "/info") @ResponseStatus(HttpStatus.OK) public ResponseEntity healthCheck() { - // Used just for health checking AppInfo info = AppInfo.builder().name(name).version(version).environment(environment).build(); return ResponseEntity.status(HttpStatus.OK).body(info); } diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsController.java b/src/main/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsController.java index 49fd7ab..963bccc 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsController.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsController.java @@ -34,6 +34,12 @@ public MdbGpsController(ModelMapper modelMapper) { this.modelMapper = modelMapper; } + /** + * Map MDB service specific data into payment option model + * + * @param mdbPaymentOptionRequest MDB data + * @return the mapped model + */ @PostMapping("") @ResponseStatus(HttpStatus.OK) @ApiResponses(value = { @@ -50,8 +56,8 @@ public MdbGpsController(ModelMapper modelMapper) { }) @Operation(summary = "Create MDB payment option", security = {@SecurityRequirement(name = "ApiKey")}) public @Valid MdbPaymentOptionResponse createMdbPaymentOption( - @RequestBody @NotNull @Valid MdbPaymentOptionRequest ciBundleAttributes + @RequestBody @NotNull @Valid MdbPaymentOptionRequest mdbPaymentOptionRequest ) { - return this.modelMapper.map(ciBundleAttributes, MdbPaymentOptionResponse.class); + return this.modelMapper.map(mdbPaymentOptionRequest, MdbPaymentOptionResponse.class); } } \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionRequest.java b/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionRequest.java index 36c84f1..52a90a1 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionRequest.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionRequest.java @@ -7,6 +7,9 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Model class that holds MDB GPS request + */ @Data @Builder @AllArgsConstructor diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionRequestProperties.java b/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionRequestProperties.java index 4277a4c..08aa1ac 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionRequestProperties.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionRequestProperties.java @@ -9,6 +9,9 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Model class that holds MDB service specific data + */ @Data @Builder @NoArgsConstructor diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionResponse.java b/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionResponse.java index a8a47c2..9c82405 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionResponse.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/model/MdbPaymentOptionResponse.java @@ -9,6 +9,9 @@ import java.util.List; +/** + * Model class that holds MDB GPS response + */ @Data @Builder @AllArgsConstructor diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/model/PaymentOption.java b/src/main/java/it/gov/pagopa/mdb/gps/service/model/PaymentOption.java index 7e68a7c..4b0873c 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/model/PaymentOption.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/model/PaymentOption.java @@ -14,6 +14,9 @@ import java.util.ArrayList; import java.util.List; +/** + * Model class that holds MDB payment option data + */ @Data @Builder @NoArgsConstructor diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/model/Stamp.java b/src/main/java/it/gov/pagopa/mdb/gps/service/model/Stamp.java index 46085d5..fce451d 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/model/Stamp.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/model/Stamp.java @@ -9,6 +9,9 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Model class that holds MDB stamp data + */ @Data @Builder @NoArgsConstructor diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/model/Transfer.java b/src/main/java/it/gov/pagopa/mdb/gps/service/model/Transfer.java index 9ea7432..d9a10c6 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/model/Transfer.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/model/Transfer.java @@ -10,6 +10,9 @@ import lombok.Data; import lombok.NoArgsConstructor; +/** + * Model class that holds MDB transfer data + */ @Data @Builder @NoArgsConstructor From c6072becb2299f95861277f2af7afadf449e47d7 Mon Sep 17 00:00:00 2001 From: giomella Date: Fri, 29 Nov 2024 14:57:15 +0100 Subject: [PATCH 04/29] [PPANTT-191] fix dependency and app configuration --- pom.xml | 41 ++----------------- .../service/config/MappingsConfiguration.java | 1 - .../mdb/gps/service/config/OpenApiConfig.java | 6 +-- .../gps/service/exception/ErrorHandler.java | 35 ---------------- src/main/resources/application.properties | 9 +++- src/test/resources/application.properties | 27 +++++++++++- 6 files changed, 40 insertions(+), 79 deletions(-) diff --git a/pom.xml b/pom.xml index 3ce9b2f..234765f 100644 --- a/pom.xml +++ b/pom.xml @@ -49,52 +49,20 @@ org.springframework.boot - spring-boot-starter-actuator + spring-boot-starter-aop - org.springframework.boot - spring-boot-starter-data-jpa - - - - org.springframework.data - spring-data-jpa - - - - org.springframework.boot - spring-boot-starter-cache - - - com.github.ben-manes.caffeine - caffeine + spring-boot-starter-actuator org.springdoc - springdoc-openapi-ui - 1.8.0 + springdoc-openapi-starter-webmvc-ui + 2.3.0 - - com.h2database - h2 - runtime - - - - org.hibernate.orm - hibernate-core - 6.1.3.Final - - - - org.springframework.cloud - spring-cloud-starter-openfeign - 4.1.2 - @@ -107,7 +75,6 @@ lombok true - co.elastic.logging logback-ecs-encoder diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/config/MappingsConfiguration.java b/src/main/java/it/gov/pagopa/mdb/gps/service/config/MappingsConfiguration.java index d328e6e..a53c3c5 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/config/MappingsConfiguration.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/config/MappingsConfiguration.java @@ -1,6 +1,5 @@ package it.gov.pagopa.mdb.gps.service.config; - import it.gov.pagopa.mdb.gps.service.mapper.ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse; import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionRequest; import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionResponse; diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/config/OpenApiConfig.java b/src/main/java/it/gov/pagopa/mdb/gps/service/config/OpenApiConfig.java index 1e8c1bc..3c68c2a 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/config/OpenApiConfig.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/config/OpenApiConfig.java @@ -21,7 +21,7 @@ import io.swagger.v3.oas.models.servers.Server; import io.swagger.v3.oas.models.servers.ServerVariable; import io.swagger.v3.oas.models.servers.ServerVariables; -import org.springdoc.core.customizers.OpenApiCustomiser; +import org.springdoc.core.customizers.GlobalOpenApiCustomizer; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -64,7 +64,7 @@ public OpenAPI customOpenAPI( } @Bean - public OpenApiCustomiser sortOperationsAlphabetically() { + public GlobalOpenApiCustomizer sortOperationsAlphabetically() { return openApi -> { Paths paths = openApi @@ -101,7 +101,7 @@ public OpenApiCustomiser sortOperationsAlphabetically() { } @Bean - public OpenApiCustomiser addCommonHeaders() { + public GlobalOpenApiCustomizer addCommonHeaders() { return openApi -> openApi .getPaths() diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/exception/ErrorHandler.java b/src/main/java/it/gov/pagopa/mdb/gps/service/exception/ErrorHandler.java index 2c655a1..23ee181 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/exception/ErrorHandler.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/exception/ErrorHandler.java @@ -2,7 +2,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import feign.FeignException; import it.gov.pagopa.mdb.gps.service.model.ProblemJson; import jakarta.validation.ConstraintViolationException; import lombok.extern.slf4j.Slf4j; @@ -153,40 +152,6 @@ public ResponseEntity handleConstraintViolationException( return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); } - /** - * Handle if a {@link FeignException} is raised - * - * @param ex {@link FeignException} exception raised - * @param request from frontend - * @return a {@link ProblemJson} as response with the cause and with an appropriated HTTP status - */ - @ExceptionHandler({FeignException.class}) - public ResponseEntity handleFeignException(final FeignException ex, final WebRequest request) { - log.warn("FeignException raised: ", ex); - - ProblemJson problem; - if (ex.responseBody().isPresent()) { - var body = new String(ex.responseBody().get().array(), StandardCharsets.UTF_8); - try { - problem = new ObjectMapper().readValue(body, ProblemJson.class); - } catch (JsonProcessingException e) { - problem = ProblemJson.builder() - .status(HttpStatus.BAD_GATEWAY.value()) - .title(AppError.RESPONSE_NOT_READABLE.getTitle()) - .detail(AppError.RESPONSE_NOT_READABLE.getDetails()) - .build(); - } - } else { - problem = ProblemJson.builder() - .status(HttpStatus.BAD_GATEWAY.value()) - .title("No Response Body") - .detail("Error with external dependency") - .build(); - } - - return new ResponseEntity<>(problem, HttpStatus.valueOf(problem.getStatus())); - } - /** * Handle if a {@link AppException} is raised * diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 5ad4771..beea1d7 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,4 +1,5 @@ # Info +info.application.name=@project.name@ info.application.artifactId=@project.artifactId@ info.application.version=@project.version@ info.application.description=@project.description@ @@ -14,12 +15,16 @@ management.health.readinessState.enabled=true springdoc.writer-with-order-by-keys=true springdoc.writer-with-default-pretty-printer=true # Server -# TODO: set your base path server.servlet.context-path=/ server.port=8080 # Logging logging.level.root=${DEFAULT_LOGGING_LEVEL:INFO} logging.level.it.gov.pagopa=${APP_LOGGING_LEVEL:INFO} # CORS configuration -cors.configuration=${CORS_CONFIGURATION:'{"origins": ["*"], "methods": ["*"]}'} +cors.configuration=${CORS_CONFIGURATION:{"origins": ["*"], "methods": ["*"]}} +# Jackson serialization +spring.jackson.default-property-inclusion=NON_NULL +spring.jackson.serialization.write-dates-as-timestamps=false +spring.jackson.serialization.fail-on-empty-beans=false +spring.jackson.deserialization.fail-on-unknown-properties=false diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index cd4c92f..b006f14 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -1,7 +1,32 @@ # Info +info.application.name=MDB GPS Service +info.application.artifactId=pagopa-gps-mdb-service +info.application.version=0.0.0 +info.application.description=MDB GPS Service info.properties.environment=test -# logging +# Actuator +management.endpoints.web.exposure.include=health,info +management.endpoints.jmx.exposure.include=health,info +management.info.env.enabled=true +management.endpoint.health.probes.enabled=true +management.health.livenessState.enabled=true +management.health.readinessState.enabled=true + +# Server +server.servlet.context-path=/ +server.port=8080 +# Logging logging.level.root=INFO logging.level.it.gov.pagopa=INFO # CORS configuration cors.configuration={"origins": ["*"], "methods": ["*"]} + +# Openapi +springdoc.writer-with-order-by-keys=true +springdoc.writer-with-default-pretty-printer=true + +# Jackson serialization +spring.jackson.default-property-inclusion=NON_NULL +spring.jackson.serialization.write-dates-as-timestamps=false +spring.jackson.serialization.fail-on-empty-beans=false +spring.jackson.deserialization.fail-on-unknown-properties=false \ No newline at end of file From 206b8ecc67061a81538d700ebec666557ab56597 Mon Sep 17 00:00:00 2001 From: giomella Date: Fri, 29 Nov 2024 14:59:36 +0100 Subject: [PATCH 05/29] [PPANTT-191] added openapi and unit tests --- openapi/openapi.json | 418 +++++++++++++++++- .../service/controller/MdbGpsController.java | 6 +- .../mdb/gps/service/model/PaymentOption.java | 3 +- .../gps/service}/ApplicationTest.java | 2 +- .../gps/service}/OpenApiGenerationTest.java | 5 +- .../controller/HomeControllerTest.java | 23 + .../controller/MdbGpsControllerTest.java | 90 ++++ 7 files changed, 537 insertions(+), 10 deletions(-) rename src/test/java/it/gov/pagopa/{microservice => mdb/gps/service}/ApplicationTest.java (89%) rename src/test/java/it/gov/pagopa/{microservice => mdb/gps/service}/OpenApiGenerationTest.java (94%) create mode 100644 src/test/java/it/gov/pagopa/mdb/gps/service/controller/HomeControllerTest.java create mode 100644 src/test/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsControllerTest.java diff --git a/openapi/openapi.json b/openapi/openapi.json index 0967ef4..4c79067 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -1 +1,417 @@ -{} +{ + "openapi": "3.0.1", + "info": { + "description": "MDB GPS Service", + "termsOfService": "https://www.pagopa.gov.it/", + "title": "pagopa-gps-mdb-service", + "version": "0.0.0" + }, + "servers": [ + { + "url": "http://localhost:8080" + }, + { + "url": "https://{host}{basePath}", + "variables": { + "basePath": { + "default": "/mdb/gps/service/v1" + }, + "host": { + "default": "api.dev.platform.pagopa.it", + "enum": [ + "api.dev.platform.pagopa.it", + "api.uat.platform.pagopa.it", + "api.platform.pagopa.it" + ] + } + } + } + ], + "paths": { + "/info": { + "get": { + "description": "Return OK if application is started", + "operationId": "healthCheck", + "responses": { + "200": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/AppInfo" + } + } + }, + "description": "OK", + "headers": { + "X-Request-Id": { + "description": "This header identifies the call", + "schema": { + "type": "string" + } + } + } + } + }, + "security": [ + { + "ApiKey": [] + } + ], + "summary": "health check", + "tags": [ + "Home" + ] + }, + "parameters": [ + { + "description": "This header identifies the call, if not passed it is self-generated. This ID is returned in the response.", + "in": "header", + "name": "X-Request-Id", + "schema": { + "type": "string" + } + } + ] + }, + "/mbd/paymentOption": { + "parameters": [ + { + "description": "This header identifies the call, if not passed it is self-generated. This ID is returned in the response.", + "in": "header", + "name": "X-Request-Id", + "schema": { + "type": "string" + } + } + ], + "post": { + "operationId": "createMdbPaymentOption", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MdbPaymentOptionRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MdbPaymentOptionResponse" + } + } + }, + "description": "OK", + "headers": { + "X-Request-Id": { + "description": "This header identifies the call", + "schema": { + "type": "string" + } + } + } + }, + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MdbPaymentOptionResponse" + } + } + }, + "description": "Created", + "headers": { + "X-Request-Id": { + "description": "This header identifies the call", + "schema": { + "type": "string" + } + } + } + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemJson" + } + } + }, + "description": "Bad Request", + "headers": { + "X-Request-Id": { + "description": "This header identifies the call", + "schema": { + "type": "string" + } + } + } + }, + "401": { + "description": "Unauthorized", + "headers": { + "X-Request-Id": { + "description": "This header identifies the call", + "schema": { + "type": "string" + } + } + } + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemJson" + } + } + }, + "description": "Not found", + "headers": { + "X-Request-Id": { + "description": "This header identifies the call", + "schema": { + "type": "string" + } + } + } + }, + "429": { + "description": "Too many requests", + "headers": { + "X-Request-Id": { + "description": "This header identifies the call", + "schema": { + "type": "string" + } + } + } + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemJson" + } + } + }, + "description": "Service unavailable", + "headers": { + "X-Request-Id": { + "description": "This header identifies the call", + "schema": { + "type": "string" + } + } + } + } + }, + "security": [ + { + "ApiKey": [] + } + ], + "summary": "Create MDB payment option", + "tags": [ + "MDB GPS" + ] + } + } + }, + "components": { + "schemas": { + "AppInfo": { + "type": "object", + "properties": { + "environment": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "MdbPaymentOptionRequest": { + "type": "object", + "properties": { + "pippo": { + "type": "string" + } + } + }, + "MdbPaymentOptionResponse": { + "type": "object", + "properties": { + "paymentOption": { + "type": "array", + "description": "MDB payment option", + "items": { + "$ref": "#/components/schemas/PaymentOption" + } + } + } + }, + "PaymentOption": { + "required": [ + "amount", + "description", + "dueDate", + "firstName", + "isPartialPayment", + "lastName" + ], + "type": "object", + "properties": { + "amount": { + "type": "integer", + "description": "Payment option's amount", + "format": "int64" + }, + "description": { + "maxLength": 140, + "minLength": 0, + "type": "string", + "description": "Payment option's description" + }, + "dueDate": { + "type": "string", + "description": "Payment option's due date", + "format": "date-time" + }, + "firstName": { + "type": "string", + "description": "Debtor's name" + }, + "isPartialPayment": { + "type": "boolean", + "description": "Payment option's is partial payment flag" + }, + "lastName": { + "type": "string", + "description": "Debtor's last name" + }, + "retentionDate": { + "type": "string", + "description": "Payment option's retention date", + "format": "date-time" + }, + "transfer": { + "type": "array", + "description": "Payment option's transfer list", + "items": { + "$ref": "#/components/schemas/Transfer" + } + } + }, + "description": "MDB payment option" + }, + "ProblemJson": { + "type": "object", + "properties": { + "detail": { + "type": "string", + "description": "A human readable explanation specific to this occurrence of the problem.", + "example": "There was an error processing the request" + }, + "status": { + "maximum": 600, + "minimum": 100, + "type": "integer", + "description": "The HTTP status code generated by the origin server for this occurrence of the problem.", + "format": "int32", + "example": 200 + }, + "title": { + "type": "string", + "description": "A short, summary of the problem type. Written in english and readable for engineers (usually not suited for non technical stakeholders and not localized); example: Service Unavailable" + } + } + }, + "Stamp": { + "required": [ + "hashDocument", + "provincialResidence", + "stampType" + ], + "type": "object", + "properties": { + "hashDocument": { + "maxLength": 72, + "minLength": 0, + "type": "string", + "description": "Document hash type is stBase64Binary72 as described in https://github.com/pagopa/pagopa-api." + }, + "provincialResidence": { + "pattern": "[A-Z]{2}", + "type": "string", + "description": "The province of residence", + "example": "RM" + }, + "stampType": { + "maxLength": 2, + "minLength": 2, + "type": "string", + "description": "The type of the stamp" + } + }, + "description": "Transfer's stamp" + }, + "Transfer": { + "required": [ + "amount", + "idTransfer", + "remittanceInformation" + ], + "type": "object", + "properties": { + "amount": { + "type": "integer", + "description": "Transfer's amount", + "format": "int64" + }, + "idTransfer": { + "type": "string", + "description": "Transfer's id", + "enum": [ + "1", + "2", + "3", + "4", + "5" + ] + }, + "organizationFiscalCode": { + "type": "string", + "description": "Fiscal code related to the organization targeted by this transfer.", + "example": "00000000000" + }, + "remittanceInformation": { + "maxLength": 140, + "minLength": 0, + "type": "string", + "description": "Transfer's remittance information" + }, + "stamp": { + "$ref": "#/components/schemas/Stamp" + } + }, + "description": "Payment option's transfer list" + } + }, + "securitySchemes": { + "ApiKey": { + "description": "The API key to access this function app.", + "in": "header", + "name": "Ocp-Apim-Subscription-Key", + "type": "apiKey" + } + } + } +} \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsController.java b/src/main/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsController.java index 963bccc..17a8233 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsController.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsController.java @@ -23,7 +23,7 @@ import org.springframework.web.bind.annotation.RestController; @RestController -@RequestMapping(value = "/mbd/paymentOption", produces = MediaType.APPLICATION_JSON_VALUE) +@RequestMapping(consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @Tag(name = "MDB GPS") public class MdbGpsController { @@ -40,8 +40,8 @@ public MdbGpsController(ModelMapper modelMapper) { * @param mdbPaymentOptionRequest MDB data * @return the mapped model */ - @PostMapping("") - @ResponseStatus(HttpStatus.OK) + @PostMapping("/mbd/paymentOption") + @ResponseStatus(HttpStatus.CREATED) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "OK", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/model/PaymentOption.java b/src/main/java/it/gov/pagopa/mdb/gps/service/model/PaymentOption.java index 4b0873c..dcb8104 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/model/PaymentOption.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/model/PaymentOption.java @@ -11,7 +11,6 @@ import lombok.NoArgsConstructor; import java.time.LocalDateTime; -import java.util.ArrayList; import java.util.List; /** @@ -53,5 +52,5 @@ public class PaymentOption { @Valid @Schema(description = "Payment option's transfer list", requiredMode = Schema.RequiredMode.REQUIRED) - private List<@Valid Transfer> transfer = new ArrayList<>(); + private List<@Valid Transfer> transfer; } \ No newline at end of file diff --git a/src/test/java/it/gov/pagopa/microservice/ApplicationTest.java b/src/test/java/it/gov/pagopa/mdb/gps/service/ApplicationTest.java similarity index 89% rename from src/test/java/it/gov/pagopa/microservice/ApplicationTest.java rename to src/test/java/it/gov/pagopa/mdb/gps/service/ApplicationTest.java index 56dcf59..a1dbbce 100644 --- a/src/test/java/it/gov/pagopa/microservice/ApplicationTest.java +++ b/src/test/java/it/gov/pagopa/mdb/gps/service/ApplicationTest.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.microservice; +package it.gov.pagopa.mdb.gps.service; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; diff --git a/src/test/java/it/gov/pagopa/microservice/OpenApiGenerationTest.java b/src/test/java/it/gov/pagopa/mdb/gps/service/OpenApiGenerationTest.java similarity index 94% rename from src/test/java/it/gov/pagopa/microservice/OpenApiGenerationTest.java rename to src/test/java/it/gov/pagopa/mdb/gps/service/OpenApiGenerationTest.java index f546ae8..83dad62 100644 --- a/src/test/java/it/gov/pagopa/microservice/OpenApiGenerationTest.java +++ b/src/test/java/it/gov/pagopa/mdb/gps/service/OpenApiGenerationTest.java @@ -1,7 +1,6 @@ -package it.gov.pagopa.microservice; +package it.gov.pagopa.mdb.gps.service; import com.fasterxml.jackson.databind.ObjectMapper; -import it.gov.pagopa.mdb.gps.service.Application; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -33,7 +32,7 @@ void swaggerSpringPlugin() throws Exception { mvc.perform(MockMvcRequestBuilders.get("/v3/api-docs").accept(MediaType.APPLICATION_JSON)) .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()) .andDo( - (result) -> { + result -> { assertNotNull(result); assertNotNull(result.getResponse()); final String content = result.getResponse().getContentAsString(); diff --git a/src/test/java/it/gov/pagopa/mdb/gps/service/controller/HomeControllerTest.java b/src/test/java/it/gov/pagopa/mdb/gps/service/controller/HomeControllerTest.java new file mode 100644 index 0000000..7e9250f --- /dev/null +++ b/src/test/java/it/gov/pagopa/mdb/gps/service/controller/HomeControllerTest.java @@ -0,0 +1,23 @@ +package it.gov.pagopa.mdb.gps.service.controller; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@AutoConfigureMockMvc +@SpringBootTest +class HomeControllerTest { + + @Autowired + private MockMvc mvc; + + @Test + void healthCheckTestSuccess() throws Exception { + mvc.perform(get("/info")).andExpect(status().isOk()); + } +} \ No newline at end of file diff --git a/src/test/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsControllerTest.java b/src/test/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsControllerTest.java new file mode 100644 index 0000000..4f25d82 --- /dev/null +++ b/src/test/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsControllerTest.java @@ -0,0 +1,90 @@ +package it.gov.pagopa.mdb.gps.service.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionRequest; +import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionRequestProperties; +import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionResponse; +import it.gov.pagopa.mdb.gps.service.model.PaymentOption; +import it.gov.pagopa.mdb.gps.service.model.Transfer; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@AutoConfigureMockMvc +@SpringBootTest +class MdbGpsControllerTest { + + @Autowired + private MockMvc mvc; + + @Autowired + private ObjectMapper objectMapper; + + @Test + void createMdbPaymentOptionTestSuccess() throws Exception { + MdbPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + + MvcResult result = mvc.perform(post("/mbd/paymentOption") + .content(objectMapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isCreated()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andReturn(); + + String json = result.getResponse().getContentAsString(); + + assertNotNull(json); + + MdbPaymentOptionResponse response = objectMapper.readValue(json, MdbPaymentOptionResponse.class); + + assertNotNull(response); + assertNotNull(response.getPaymentOption()); + assertEquals(1, response.getPaymentOption().size()); + + PaymentOption paymentOption = response.getPaymentOption().get(0); + assertEquals(request.getProperties().getFirstName(), paymentOption.getFirstName()); + assertEquals(request.getProperties().getLastName(), paymentOption.getLastName()); + assertEquals(request.getProperties().getAmount(), paymentOption.getAmount()); + assertEquals(request.getProperties().getDescription(), paymentOption.getDescription()); + assertNotNull(paymentOption.getDueDate()); + assertNotNull(paymentOption.getRetentionDate()); + assertFalse(paymentOption.getIsPartialPayment()); + assertNotNull(paymentOption.getTransfer()); + assertEquals(1, paymentOption.getTransfer().size()); + + Transfer transfer = paymentOption.getTransfer().get(0); + assertEquals(request.getProperties().getAmount(), transfer.getAmount()); + assertEquals(request.getProperties().getFiscalCode(), transfer.getOrganizationFiscalCode()); + assertEquals("1", transfer.getIdTransfer()); + assertEquals("Pagamento MDB", transfer.getRemittanceInformation()); + assertNotNull(transfer.getStamp()); + assertEquals(request.getProperties().getProvincialResidence(), transfer.getStamp().getProvincialResidence()); + assertEquals(request.getProperties().getDocumentHash(), transfer.getStamp().getHashDocument()); + assertEquals("st", transfer.getStamp().getStampType()); + } + + private MdbPaymentOptionRequest buildMdbPaymentOptionRequest() { + return MdbPaymentOptionRequest.builder() + .properties(MdbPaymentOptionRequestProperties.builder() + .amount(16L) + .description("description") + .firstName("Mario") + .lastName("Rossi") + .fiscalCode("0000000000000000") + .provincialResidence("AS") + .documentHash("1trA5qyjSZNwiwtGG46dyjRpL16TFgGCFvnfFzQrFHbB") + .build()) + .build(); + } +} \ No newline at end of file From ab56419a2825c5ce3b47bff8e099f48b36aaf5ca Mon Sep 17 00:00:00 2001 From: giomella Date: Fri, 29 Nov 2024 16:30:00 +0100 Subject: [PATCH 06/29] [PPANTT-191] update model and converter by providing parameter via application properties --- .../service/config/MappingsConfiguration.java | 16 ++++----- ...tionRequestToMdbPaymentOptionResponse.java | 32 +++++++++++++---- .../MdbPaymentOptionRequestProperties.java | 4 --- .../resources/application-local.properties | 36 +++++++++++++++++++ src/main/resources/application.properties | 13 +++++++ .../controller/MdbGpsControllerTest.java | 5 ++- src/test/resources/application.properties | 13 ++++++- 7 files changed, 97 insertions(+), 22 deletions(-) diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/config/MappingsConfiguration.java b/src/main/java/it/gov/pagopa/mdb/gps/service/config/MappingsConfiguration.java index a53c3c5..7e7c20c 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/config/MappingsConfiguration.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/config/MappingsConfiguration.java @@ -11,13 +11,13 @@ @Configuration public class MappingsConfiguration { - @Bean - ModelMapper modelMapper() { - ModelMapper mapper = new ModelMapper(); - mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); + @Bean + ModelMapper modelMapper(ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse mdbPaymentOptionResponseConverter) { + ModelMapper mapper = new ModelMapper(); + mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); - mapper.createTypeMap(MdbPaymentOptionRequest.class, MdbPaymentOptionResponse.class) - .setConverter(new ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse()); - return mapper; - } + mapper.createTypeMap(MdbPaymentOptionRequest.class, MdbPaymentOptionResponse.class) + .setConverter(mdbPaymentOptionResponseConverter); + return mapper; + } } diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/mapper/ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse.java b/src/main/java/it/gov/pagopa/mdb/gps/service/mapper/ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse.java index 97b42f0..79d006e 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/mapper/ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse.java +++ b/src/main/java/it/gov/pagopa/mdb/gps/service/mapper/ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse.java @@ -8,20 +8,41 @@ import it.gov.pagopa.mdb.gps.service.model.Transfer; import org.modelmapper.Converter; import org.modelmapper.spi.MappingContext; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.Collections; /** * Converter class that specify how to convert a {@link MdbPaymentOptionRequest} instance to a {@link MdbPaymentOptionResponse} instance */ +@Component public class ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse implements Converter { private static final boolean IS_PARTIAL_PAYMENT = false; private static final String ID_TRANSFER = "1"; - private static final String REMITTANCE_INFORMATION = "Pagamento MDB"; private static final String STAMP_TYPE = "st"; + @Value("${mbd.payment-option.description}") + private String description; + + @Value("${mbd.transfer.remittance-information}") + private String remittanceInformation; + + @Value("${mbd.payment-option.due-date-delta}") + private int dueDateDelta; + + @Value("${mbd.payment-option.due-date-delta-time-unit}") + private ChronoUnit dueDateDeltaTimeUnit; + + @Value("${mbd.payment-option.retention-date-delta}") + private int retentionDateDelta; + + @Value("${mbd.payment-option.retention-date-delta-time-unit}") + private ChronoUnit retentionDateDeltaTimeUnit; + @Override public MdbPaymentOptionResponse convert(MappingContext context) { MdbPaymentOptionRequestProperties model = context.getSource().getProperties(); @@ -30,7 +51,7 @@ public MdbPaymentOptionResponse convert(MappingContext Date: Fri, 29 Nov 2024 16:46:32 +0100 Subject: [PATCH 07/29] [PPANTT-191] added unit tests --- .../controller/MdbGpsControllerTest.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/src/test/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsControllerTest.java b/src/test/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsControllerTest.java index e8d26c9..7f27b8b 100644 --- a/src/test/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsControllerTest.java +++ b/src/test/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsControllerTest.java @@ -74,6 +74,90 @@ void createMdbPaymentOptionTestSuccess() throws Exception { assertEquals("st", transfer.getStamp().getStampType()); } + @Test + void createMdbPaymentOptionTestFailAmountMissing() throws Exception { + MdbPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + request.getProperties().setAmount(null); + + mvc.perform(post("/mbd/paymentOption") + .content(objectMapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()); + + } + + @Test + void createMdbPaymentOptionTestFailFirstNameMissing() throws Exception { + MdbPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + request.getProperties().setFirstName(null); + + mvc.perform(post("/mbd/paymentOption") + .content(objectMapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()); + + } + + @Test + void createMdbPaymentOptionTestFailLastNameMissing() throws Exception { + MdbPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + request.getProperties().setLastName(null); + + mvc.perform(post("/mbd/paymentOption") + .content(objectMapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()); + + } + + @Test + void createMdbPaymentOptionTestFailFiscalCodeMissing() throws Exception { + MdbPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + request.getProperties().setFiscalCode(null); + + mvc.perform(post("/mbd/paymentOption") + .content(objectMapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()); + + } + + @Test + void createMdbPaymentOptionTestFailProvincialResidenceMissing() throws Exception { + MdbPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + request.getProperties().setProvincialResidence(null); + + mvc.perform(post("/mbd/paymentOption") + .content(objectMapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()); + + } + + @Test + void createMdbPaymentOptionTestFailDocumentHashMissing() throws Exception { + MdbPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + request.getProperties().setDocumentHash(null); + + mvc.perform(post("/mbd/paymentOption") + .content(objectMapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()); + + } + + @Test + void createMdbPaymentOptionTestFailDocumentHashWrongSize() throws Exception { + MdbPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + request.getProperties().setDocumentHash("asdfsdf"); + + mvc.perform(post("/mbd/paymentOption") + .content(objectMapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()); + + } + private MdbPaymentOptionRequest buildMdbPaymentOptionRequest() { return MdbPaymentOptionRequest.builder() .properties(MdbPaymentOptionRequestProperties.builder() From ec5fb3f6457aeacf5a0e638cb71299fae2e3b4ae Mon Sep 17 00:00:00 2001 From: giomella Date: Fri, 29 Nov 2024 18:14:47 +0100 Subject: [PATCH 08/29] [PPANTT-191] fix --- openapi/openapi.json | 82 +++++++++++++++---- .../{mdb => mbd}/gps/service/Application.java | 2 +- .../gps/service/config/LoggingAspect.java | 8 +- .../service/config/MappingsConfiguration.java | 12 +-- .../gps/service/config/OpenApiConfig.java | 6 +- .../gps/service/config/RequestFilter.java | 4 +- .../gps/service/config/ResponseValidator.java | 6 +- .../service/config/WebMvcConfiguration.java | 4 +- .../service/controller/HomeController.java | 4 +- .../service/controller/MbdGpsController.java} | 28 +++---- .../gps/service/exception/AppError.java | 2 +- .../gps/service/exception/AppException.java | 2 +- .../gps/service/exception/ErrorHandler.java | 7 +- ...ionRequestToMbdPaymentOptionResponse.java} | 24 +++--- .../service/model/AppCorsConfiguration.java | 2 +- .../gps/service/model/AppInfo.java | 2 +- .../model/MbdPaymentOptionRequest.java} | 10 +-- .../MbdPaymentOptionRequestProperties.java} | 10 +-- .../model/MbdPaymentOptionResponse.java} | 8 +- .../gps/service/model/PaymentOption.java | 4 +- .../gps/service/model/ProblemJson.java | 5 +- .../{mdb => mbd}/gps/service/model/Stamp.java | 4 +- .../gps/service/model/Transfer.java | 4 +- .../gps/service/util/CommonUtility.java | 2 +- .../gps/service/util/Constants.java | 2 +- .../gps/service/ApplicationTest.java | 2 +- .../gps/service/OpenApiGenerationTest.java | 2 +- .../controller/HomeControllerTest.java | 2 +- .../controller/MbdGpsControllerTest.java} | 38 ++++----- src/test/resources/application.properties | 6 +- 30 files changed, 171 insertions(+), 123 deletions(-) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/Application.java (87%) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/config/LoggingAspect.java (96%) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/config/MappingsConfiguration.java (59%) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/config/OpenApiConfig.java (97%) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/config/RequestFilter.java (94%) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/config/ResponseValidator.java (91%) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/config/WebMvcConfiguration.java (89%) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/controller/HomeController.java (94%) rename src/main/java/it/gov/pagopa/{mdb/gps/service/controller/MdbGpsController.java => mbd/gps/service/controller/MbdGpsController.java} (74%) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/exception/AppError.java (94%) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/exception/AppException.java (98%) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/exception/ErrorHandler.java (96%) rename src/main/java/it/gov/pagopa/{mdb/gps/service/mapper/ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse.java => mbd/gps/service/mapper/ConvertMbdPaymentOptionRequestToMbdPaymentOptionResponse.java} (72%) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/model/AppCorsConfiguration.java (92%) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/model/AppInfo.java (91%) rename src/main/java/it/gov/pagopa/{mdb/gps/service/model/MdbPaymentOptionRequest.java => mbd/gps/service/model/MbdPaymentOptionRequest.java} (55%) rename src/main/java/it/gov/pagopa/{mdb/gps/service/model/MdbPaymentOptionRequestProperties.java => mbd/gps/service/model/MbdPaymentOptionRequestProperties.java} (80%) rename src/main/java/it/gov/pagopa/{mdb/gps/service/model/MdbPaymentOptionResponse.java => mbd/gps/service/model/MbdPaymentOptionResponse.java} (66%) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/model/PaymentOption.java (95%) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/model/ProblemJson.java (90%) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/model/Stamp.java (94%) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/model/Transfer.java (94%) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/util/CommonUtility.java (97%) rename src/main/java/it/gov/pagopa/{mdb => mbd}/gps/service/util/Constants.java (77%) rename src/test/java/it/gov/pagopa/{mdb => mbd}/gps/service/ApplicationTest.java (89%) rename src/test/java/it/gov/pagopa/{mdb => mbd}/gps/service/OpenApiGenerationTest.java (98%) rename src/test/java/it/gov/pagopa/{mdb => mbd}/gps/service/controller/HomeControllerTest.java (93%) rename src/test/java/it/gov/pagopa/{mdb/gps/service/controller/MdbGpsControllerTest.java => mbd/gps/service/controller/MbdGpsControllerTest.java} (84%) diff --git a/openapi/openapi.json b/openapi/openapi.json index 4c79067..3350f3d 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -1,9 +1,9 @@ { "openapi": "3.0.1", "info": { - "description": "MDB GPS Service", + "description": "MBD GPS Service", "termsOfService": "https://www.pagopa.gov.it/", - "title": "pagopa-gps-mdb-service", + "title": "pagopa-gps-mbd-service", "version": "0.0.0" }, "servers": [ @@ -14,7 +14,7 @@ "url": "https://{host}{basePath}", "variables": { "basePath": { - "default": "/mdb/gps/service/v1" + "default": "/pagopa-mbd-gps-service/v1" }, "host": { "default": "api.dev.platform.pagopa.it", @@ -90,7 +90,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MdbPaymentOptionRequest" + "$ref": "#/components/schemas/MbdPaymentOptionRequest" } } }, @@ -101,7 +101,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MdbPaymentOptionResponse" + "$ref": "#/components/schemas/MbdPaymentOptionResponse" } } }, @@ -119,7 +119,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MdbPaymentOptionResponse" + "$ref": "#/components/schemas/MbdPaymentOptionResponse" } } }, @@ -215,9 +215,9 @@ "ApiKey": [] } ], - "summary": "Create MDB payment option", + "summary": "Create MBD payment option", "tags": [ - "MDB GPS" + "MBD GPS" ] } } @@ -238,20 +238,67 @@ } } }, - "MdbPaymentOptionRequest": { + "MbdPaymentOptionRequest": { + "required": [ + "properties" + ], "type": "object", "properties": { - "pippo": { - "type": "string" + "properties": { + "$ref": "#/components/schemas/MbdPaymentOptionRequestProperties" } } }, - "MdbPaymentOptionResponse": { + "MbdPaymentOptionRequestProperties": { + "required": [ + "amount", + "documentHash", + "firstName", + "fiscalCode", + "lastName", + "provincialResidence" + ], + "type": "object", + "properties": { + "amount": { + "type": "integer", + "description": "MBD amount", + "format": "int64" + }, + "documentHash": { + "maxLength": 44, + "minLength": 44, + "type": "string", + "description": "MBD document's hash" + }, + "firstName": { + "type": "string", + "description": "Debtor's name" + }, + "fiscalCode": { + "type": "string", + "description": "Debtor's fiscal code" + }, + "lastName": { + "type": "string", + "description": "Debtor's last name" + }, + "provincialResidence": { + "type": "string", + "description": "Debtor's residence province" + } + }, + "description": "MBD payment option's properties" + }, + "MbdPaymentOptionResponse": { + "required": [ + "paymentOption" + ], "type": "object", "properties": { "paymentOption": { "type": "array", - "description": "MDB payment option", + "description": "MBD payment option", "items": { "$ref": "#/components/schemas/PaymentOption" } @@ -265,7 +312,9 @@ "dueDate", "firstName", "isPartialPayment", - "lastName" + "lastName", + "retentionDate", + "transfer" ], "type": "object", "properties": { @@ -310,7 +359,7 @@ } } }, - "description": "MDB payment option" + "description": "MBD payment option" }, "ProblemJson": { "type": "object", @@ -367,7 +416,8 @@ "required": [ "amount", "idTransfer", - "remittanceInformation" + "remittanceInformation", + "stamp" ], "type": "object", "properties": { diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/Application.java b/src/main/java/it/gov/pagopa/mbd/gps/service/Application.java similarity index 87% rename from src/main/java/it/gov/pagopa/mdb/gps/service/Application.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/Application.java index cad8802..120d1c9 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/Application.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/Application.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.mdb.gps.service; +package it.gov.pagopa.mbd.gps.service; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/config/LoggingAspect.java b/src/main/java/it/gov/pagopa/mbd/gps/service/config/LoggingAspect.java similarity index 96% rename from src/main/java/it/gov/pagopa/mdb/gps/service/config/LoggingAspect.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/config/LoggingAspect.java index 8a6cac3..209363a 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/config/LoggingAspect.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/config/LoggingAspect.java @@ -1,7 +1,7 @@ -package it.gov.pagopa.mdb.gps.service.config; +package it.gov.pagopa.mbd.gps.service.config; -import it.gov.pagopa.mdb.gps.service.exception.AppError; -import it.gov.pagopa.mdb.gps.service.model.ProblemJson; +import it.gov.pagopa.mbd.gps.service.exception.AppError; +import it.gov.pagopa.mbd.gps.service.model.ProblemJson; import jakarta.annotation.PostConstruct; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -23,7 +23,7 @@ import java.util.Map; import java.util.UUID; -import static it.gov.pagopa.mdb.gps.service.util.CommonUtility.deNull; +import static it.gov.pagopa.mbd.gps.service.util.CommonUtility.deNull; @Aspect @Component diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/config/MappingsConfiguration.java b/src/main/java/it/gov/pagopa/mbd/gps/service/config/MappingsConfiguration.java similarity index 59% rename from src/main/java/it/gov/pagopa/mdb/gps/service/config/MappingsConfiguration.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/config/MappingsConfiguration.java index 7e7c20c..76cf545 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/config/MappingsConfiguration.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/config/MappingsConfiguration.java @@ -1,8 +1,8 @@ -package it.gov.pagopa.mdb.gps.service.config; +package it.gov.pagopa.mbd.gps.service.config; -import it.gov.pagopa.mdb.gps.service.mapper.ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse; -import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionRequest; -import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionResponse; +import it.gov.pagopa.mbd.gps.service.mapper.ConvertMbdPaymentOptionRequestToMbdPaymentOptionResponse; +import it.gov.pagopa.mbd.gps.service.model.MbdPaymentOptionRequest; +import it.gov.pagopa.mbd.gps.service.model.MbdPaymentOptionResponse; import org.modelmapper.ModelMapper; import org.modelmapper.convention.MatchingStrategies; import org.springframework.context.annotation.Bean; @@ -12,11 +12,11 @@ public class MappingsConfiguration { @Bean - ModelMapper modelMapper(ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse mdbPaymentOptionResponseConverter) { + ModelMapper modelMapper(ConvertMbdPaymentOptionRequestToMbdPaymentOptionResponse mdbPaymentOptionResponseConverter) { ModelMapper mapper = new ModelMapper(); mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); - mapper.createTypeMap(MdbPaymentOptionRequest.class, MdbPaymentOptionResponse.class) + mapper.createTypeMap(MbdPaymentOptionRequest.class, MbdPaymentOptionResponse.class) .setConverter(mdbPaymentOptionResponseConverter); return mapper; } diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/config/OpenApiConfig.java b/src/main/java/it/gov/pagopa/mbd/gps/service/config/OpenApiConfig.java similarity index 97% rename from src/main/java/it/gov/pagopa/mdb/gps/service/config/OpenApiConfig.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/config/OpenApiConfig.java index 3c68c2a..c5a65a2 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/config/OpenApiConfig.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/config/OpenApiConfig.java @@ -1,6 +1,6 @@ -package it.gov.pagopa.mdb.gps.service.config; +package it.gov.pagopa.mbd.gps.service.config; -import static it.gov.pagopa.mdb.gps.service.util.Constants.HEADER_REQUEST_ID; +import static it.gov.pagopa.mbd.gps.service.util.Constants.HEADER_REQUEST_ID; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; @@ -29,7 +29,7 @@ @Configuration public class OpenApiConfig { - public static final String BASE_PATH = "/mdb/gps/service/v1"; + public static final String BASE_PATH = "/pagopa-mbd-gps-service/v1"; @Bean public OpenAPI customOpenAPI( diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/config/RequestFilter.java b/src/main/java/it/gov/pagopa/mbd/gps/service/config/RequestFilter.java similarity index 94% rename from src/main/java/it/gov/pagopa/mdb/gps/service/config/RequestFilter.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/config/RequestFilter.java index 5f58ee5..d18f74a 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/config/RequestFilter.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/config/RequestFilter.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.mdb.gps.service.config; +package it.gov.pagopa.mbd.gps.service.config; import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; @@ -16,7 +16,7 @@ import java.io.IOException; import java.util.UUID; -import static it.gov.pagopa.mdb.gps.service.util.Constants.HEADER_REQUEST_ID; +import static it.gov.pagopa.mbd.gps.service.util.Constants.HEADER_REQUEST_ID; @Component @Order(Ordered.HIGHEST_PRECEDENCE) diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/config/ResponseValidator.java b/src/main/java/it/gov/pagopa/mbd/gps/service/config/ResponseValidator.java similarity index 91% rename from src/main/java/it/gov/pagopa/mdb/gps/service/config/ResponseValidator.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/config/ResponseValidator.java index 0a2ae65..ccfa67a 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/config/ResponseValidator.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/config/ResponseValidator.java @@ -1,6 +1,6 @@ -package it.gov.pagopa.mdb.gps.service.config; +package it.gov.pagopa.mbd.gps.service.config; -import it.gov.pagopa.mdb.gps.service.exception.AppException; +import it.gov.pagopa.mbd.gps.service.exception.AppException; import jakarta.validation.ConstraintViolation; import jakarta.validation.Validator; import org.apache.commons.lang3.StringUtils; @@ -31,7 +31,7 @@ public ResponseValidator(Validator validator) { * @param joinPoint not used * @param result the response to validate */ - @AfterReturning(pointcut = "execution(* it.gov.pagopa.mdb.gps.service.controller.*.*(..))", returning = "result") + @AfterReturning(pointcut = "execution(* it.gov.pagopa.mbd.gps.service.controller.*.*(..))", returning = "result") public void validateResponse(JoinPoint joinPoint, Object result) { if (result instanceof ResponseEntity) { validateResponse((ResponseEntity) result); diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/config/WebMvcConfiguration.java b/src/main/java/it/gov/pagopa/mbd/gps/service/config/WebMvcConfiguration.java similarity index 89% rename from src/main/java/it/gov/pagopa/mdb/gps/service/config/WebMvcConfiguration.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/config/WebMvcConfiguration.java index f6b3397..2cbbfc3 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/config/WebMvcConfiguration.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/config/WebMvcConfiguration.java @@ -1,7 +1,7 @@ -package it.gov.pagopa.mdb.gps.service.config; +package it.gov.pagopa.mbd.gps.service.config; import com.fasterxml.jackson.databind.ObjectMapper; -import it.gov.pagopa.mdb.gps.service.model.AppCorsConfiguration; +import it.gov.pagopa.mbd.gps.service.model.AppCorsConfiguration; import lombok.SneakyThrows; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/controller/HomeController.java b/src/main/java/it/gov/pagopa/mbd/gps/service/controller/HomeController.java similarity index 94% rename from src/main/java/it/gov/pagopa/mdb/gps/service/controller/HomeController.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/controller/HomeController.java index 83d9f27..d53971a 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/controller/HomeController.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/controller/HomeController.java @@ -1,9 +1,9 @@ -package it.gov.pagopa.mdb.gps.service.controller; +package it.gov.pagopa.mbd.gps.service.controller; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import it.gov.pagopa.mdb.gps.service.model.AppInfo; +import it.gov.pagopa.mbd.gps.service.model.AppInfo; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsController.java b/src/main/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsController.java similarity index 74% rename from src/main/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsController.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsController.java index 17a8233..47bf223 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsController.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsController.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.mdb.gps.service.controller; +package it.gov.pagopa.mbd.gps.service.controller; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -7,9 +7,9 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; -import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionRequest; -import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionResponse; -import it.gov.pagopa.mdb.gps.service.model.ProblemJson; +import it.gov.pagopa.mbd.gps.service.model.MbdPaymentOptionRequest; +import it.gov.pagopa.mbd.gps.service.model.MbdPaymentOptionResponse; +import it.gov.pagopa.mbd.gps.service.model.ProblemJson; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import org.modelmapper.ModelMapper; @@ -24,20 +24,20 @@ @RestController @RequestMapping(consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) -@Tag(name = "MDB GPS") -public class MdbGpsController { +@Tag(name = "MBD GPS") +public class MbdGpsController { private final ModelMapper modelMapper; @Autowired - public MdbGpsController(ModelMapper modelMapper) { + public MbdGpsController(ModelMapper modelMapper) { this.modelMapper = modelMapper; } /** - * Map MDB service specific data into payment option model + * Map MBD service specific data into payment option model * - * @param mdbPaymentOptionRequest MDB data + * @param mbdPaymentOptionRequest MBD data * @return the mapped model */ @PostMapping("/mbd/paymentOption") @@ -45,7 +45,7 @@ public MdbGpsController(ModelMapper modelMapper) { @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "OK", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, - schema = @Schema(implementation = MdbPaymentOptionResponse.class))), + schema = @Schema(implementation = MbdPaymentOptionResponse.class))), @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ProblemJson.class))), @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(schema = @Schema())), @@ -54,10 +54,10 @@ public MdbGpsController(ModelMapper modelMapper) { @ApiResponse(responseCode = "500", description = "Service unavailable", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ProblemJson.class))) }) - @Operation(summary = "Create MDB payment option", security = {@SecurityRequirement(name = "ApiKey")}) - public @Valid MdbPaymentOptionResponse createMdbPaymentOption( - @RequestBody @NotNull @Valid MdbPaymentOptionRequest mdbPaymentOptionRequest + @Operation(summary = "Create MBD payment option", security = {@SecurityRequirement(name = "ApiKey")}) + public @Valid MbdPaymentOptionResponse createMdbPaymentOption( + @RequestBody @NotNull @Valid MbdPaymentOptionRequest mbdPaymentOptionRequest ) { - return this.modelMapper.map(mdbPaymentOptionRequest, MdbPaymentOptionResponse.class); + return this.modelMapper.map(mbdPaymentOptionRequest, MbdPaymentOptionResponse.class); } } \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/exception/AppError.java b/src/main/java/it/gov/pagopa/mbd/gps/service/exception/AppError.java similarity index 94% rename from src/main/java/it/gov/pagopa/mdb/gps/service/exception/AppError.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/exception/AppError.java index 2acbc10..e1226ad 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/exception/AppError.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/exception/AppError.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.mdb.gps.service.exception; +package it.gov.pagopa.mbd.gps.service.exception; import lombok.Getter; import org.springframework.http.HttpStatus; diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/exception/AppException.java b/src/main/java/it/gov/pagopa/mbd/gps/service/exception/AppException.java similarity index 98% rename from src/main/java/it/gov/pagopa/mdb/gps/service/exception/AppException.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/exception/AppException.java index c3af0c4..91fdbe3 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/exception/AppException.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/exception/AppException.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.mdb.gps.service.exception; +package it.gov.pagopa.mbd.gps.service.exception; import jakarta.validation.constraints.NotNull; import lombok.EqualsAndHashCode; diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/exception/ErrorHandler.java b/src/main/java/it/gov/pagopa/mbd/gps/service/exception/ErrorHandler.java similarity index 96% rename from src/main/java/it/gov/pagopa/mdb/gps/service/exception/ErrorHandler.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/exception/ErrorHandler.java index 23ee181..2889a81 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/exception/ErrorHandler.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/exception/ErrorHandler.java @@ -1,8 +1,6 @@ -package it.gov.pagopa.mdb.gps.service.exception; +package it.gov.pagopa.mbd.gps.service.exception; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import it.gov.pagopa.mdb.gps.service.model.ProblemJson; +import it.gov.pagopa.mbd.gps.service.model.ProblemJson; import jakarta.validation.ConstraintViolationException; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.TypeMismatchException; @@ -20,7 +18,6 @@ import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/mapper/ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse.java b/src/main/java/it/gov/pagopa/mbd/gps/service/mapper/ConvertMbdPaymentOptionRequestToMbdPaymentOptionResponse.java similarity index 72% rename from src/main/java/it/gov/pagopa/mdb/gps/service/mapper/ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/mapper/ConvertMbdPaymentOptionRequestToMbdPaymentOptionResponse.java index 79d006e..216ae3a 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/mapper/ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/mapper/ConvertMbdPaymentOptionRequestToMbdPaymentOptionResponse.java @@ -1,11 +1,11 @@ -package it.gov.pagopa.mdb.gps.service.mapper; +package it.gov.pagopa.mbd.gps.service.mapper; -import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionRequest; -import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionRequestProperties; -import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionResponse; -import it.gov.pagopa.mdb.gps.service.model.PaymentOption; -import it.gov.pagopa.mdb.gps.service.model.Stamp; -import it.gov.pagopa.mdb.gps.service.model.Transfer; +import it.gov.pagopa.mbd.gps.service.model.MbdPaymentOptionRequestProperties; +import it.gov.pagopa.mbd.gps.service.model.PaymentOption; +import it.gov.pagopa.mbd.gps.service.model.MbdPaymentOptionRequest; +import it.gov.pagopa.mbd.gps.service.model.MbdPaymentOptionResponse; +import it.gov.pagopa.mbd.gps.service.model.Stamp; +import it.gov.pagopa.mbd.gps.service.model.Transfer; import org.modelmapper.Converter; import org.modelmapper.spi.MappingContext; import org.springframework.beans.factory.annotation.Value; @@ -16,10 +16,10 @@ import java.util.Collections; /** - * Converter class that specify how to convert a {@link MdbPaymentOptionRequest} instance to a {@link MdbPaymentOptionResponse} instance + * Converter class that specify how to convert a {@link MbdPaymentOptionRequest} instance to a {@link MbdPaymentOptionResponse} instance */ @Component -public class ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse implements Converter { +public class ConvertMbdPaymentOptionRequestToMbdPaymentOptionResponse implements Converter { private static final boolean IS_PARTIAL_PAYMENT = false; private static final String ID_TRANSFER = "1"; @@ -44,8 +44,8 @@ public class ConvertMdbPaymentOptionRequestToMdbPaymentOptionResponse implements private ChronoUnit retentionDateDeltaTimeUnit; @Override - public MdbPaymentOptionResponse convert(MappingContext context) { - MdbPaymentOptionRequestProperties model = context.getSource().getProperties(); + public MbdPaymentOptionResponse convert(MappingContext context) { + MbdPaymentOptionRequestProperties model = context.getSource().getProperties(); Transfer transfer = Transfer.builder() .amount(model.getAmount()) @@ -70,7 +70,7 @@ public MdbPaymentOptionResponse convert(MappingContext paymentOption; } \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/model/PaymentOption.java b/src/main/java/it/gov/pagopa/mbd/gps/service/model/PaymentOption.java similarity index 95% rename from src/main/java/it/gov/pagopa/mdb/gps/service/model/PaymentOption.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/model/PaymentOption.java index dcb8104..c37dec9 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/model/PaymentOption.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/model/PaymentOption.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.mdb.gps.service.model; +package it.gov.pagopa.mbd.gps.service.model; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; @@ -14,7 +14,7 @@ import java.util.List; /** - * Model class that holds MDB payment option data + * Model class that holds MBD payment option data */ @Data @Builder diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/model/ProblemJson.java b/src/main/java/it/gov/pagopa/mbd/gps/service/model/ProblemJson.java similarity index 90% rename from src/main/java/it/gov/pagopa/mdb/gps/service/model/ProblemJson.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/model/ProblemJson.java index 01c3f38..0f37bfd 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/model/ProblemJson.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/model/ProblemJson.java @@ -1,8 +1,9 @@ -package it.gov.pagopa.mdb.gps.service.model; +package it.gov.pagopa.mbd.gps.service.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; +import it.gov.pagopa.mbd.gps.service.exception.ErrorHandler; import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; import lombok.AllArgsConstructor; @@ -13,7 +14,7 @@ /** * Object returned as response in case of an error. - *

See {@link it.gov.pagopa.mdb.gps.service.exception.ErrorHandler} + *

See {@link ErrorHandler} */ @Data @Builder(toBuilder = true) diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/model/Stamp.java b/src/main/java/it/gov/pagopa/mbd/gps/service/model/Stamp.java similarity index 94% rename from src/main/java/it/gov/pagopa/mdb/gps/service/model/Stamp.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/model/Stamp.java index fce451d..2a4ecf2 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/model/Stamp.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/model/Stamp.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.mdb.gps.service.model; +package it.gov.pagopa.mbd.gps.service.model; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; @@ -10,7 +10,7 @@ import lombok.NoArgsConstructor; /** - * Model class that holds MDB stamp data + * Model class that holds MBD stamp data */ @Data @Builder diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/model/Transfer.java b/src/main/java/it/gov/pagopa/mbd/gps/service/model/Transfer.java similarity index 94% rename from src/main/java/it/gov/pagopa/mdb/gps/service/model/Transfer.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/model/Transfer.java index d9a10c6..b452f9d 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/model/Transfer.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/model/Transfer.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.mdb.gps.service.model; +package it.gov.pagopa.mbd.gps.service.model; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; @@ -11,7 +11,7 @@ import lombok.NoArgsConstructor; /** - * Model class that holds MDB transfer data + * Model class that holds MBD transfer data */ @Data @Builder diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/util/CommonUtility.java b/src/main/java/it/gov/pagopa/mbd/gps/service/util/CommonUtility.java similarity index 97% rename from src/main/java/it/gov/pagopa/mdb/gps/service/util/CommonUtility.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/util/CommonUtility.java index ff5a1b7..9cdba43 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/util/CommonUtility.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/util/CommonUtility.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.mdb.gps.service.util; +package it.gov.pagopa.mbd.gps.service.util; import lombok.AccessLevel; import lombok.NoArgsConstructor; diff --git a/src/main/java/it/gov/pagopa/mdb/gps/service/util/Constants.java b/src/main/java/it/gov/pagopa/mbd/gps/service/util/Constants.java similarity index 77% rename from src/main/java/it/gov/pagopa/mdb/gps/service/util/Constants.java rename to src/main/java/it/gov/pagopa/mbd/gps/service/util/Constants.java index fd1b860..c56ece4 100644 --- a/src/main/java/it/gov/pagopa/mdb/gps/service/util/Constants.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/util/Constants.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.mdb.gps.service.util; +package it.gov.pagopa.mbd.gps.service.util; import lombok.experimental.UtilityClass; diff --git a/src/test/java/it/gov/pagopa/mdb/gps/service/ApplicationTest.java b/src/test/java/it/gov/pagopa/mbd/gps/service/ApplicationTest.java similarity index 89% rename from src/test/java/it/gov/pagopa/mdb/gps/service/ApplicationTest.java rename to src/test/java/it/gov/pagopa/mbd/gps/service/ApplicationTest.java index a1dbbce..dda87cb 100644 --- a/src/test/java/it/gov/pagopa/mdb/gps/service/ApplicationTest.java +++ b/src/test/java/it/gov/pagopa/mbd/gps/service/ApplicationTest.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.mdb.gps.service; +package it.gov.pagopa.mbd.gps.service; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; diff --git a/src/test/java/it/gov/pagopa/mdb/gps/service/OpenApiGenerationTest.java b/src/test/java/it/gov/pagopa/mbd/gps/service/OpenApiGenerationTest.java similarity index 98% rename from src/test/java/it/gov/pagopa/mdb/gps/service/OpenApiGenerationTest.java rename to src/test/java/it/gov/pagopa/mbd/gps/service/OpenApiGenerationTest.java index 83dad62..8fbba35 100644 --- a/src/test/java/it/gov/pagopa/mdb/gps/service/OpenApiGenerationTest.java +++ b/src/test/java/it/gov/pagopa/mbd/gps/service/OpenApiGenerationTest.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.mdb.gps.service; +package it.gov.pagopa.mbd.gps.service; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; diff --git a/src/test/java/it/gov/pagopa/mdb/gps/service/controller/HomeControllerTest.java b/src/test/java/it/gov/pagopa/mbd/gps/service/controller/HomeControllerTest.java similarity index 93% rename from src/test/java/it/gov/pagopa/mdb/gps/service/controller/HomeControllerTest.java rename to src/test/java/it/gov/pagopa/mbd/gps/service/controller/HomeControllerTest.java index 7e9250f..59ea9bb 100644 --- a/src/test/java/it/gov/pagopa/mdb/gps/service/controller/HomeControllerTest.java +++ b/src/test/java/it/gov/pagopa/mbd/gps/service/controller/HomeControllerTest.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.mdb.gps.service.controller; +package it.gov.pagopa.mbd.gps.service.controller; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/test/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsControllerTest.java b/src/test/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsControllerTest.java similarity index 84% rename from src/test/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsControllerTest.java rename to src/test/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsControllerTest.java index 7f27b8b..1a40e4f 100644 --- a/src/test/java/it/gov/pagopa/mdb/gps/service/controller/MdbGpsControllerTest.java +++ b/src/test/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsControllerTest.java @@ -1,11 +1,11 @@ -package it.gov.pagopa.mdb.gps.service.controller; +package it.gov.pagopa.mbd.gps.service.controller; import com.fasterxml.jackson.databind.ObjectMapper; -import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionRequest; -import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionRequestProperties; -import it.gov.pagopa.mdb.gps.service.model.MdbPaymentOptionResponse; -import it.gov.pagopa.mdb.gps.service.model.PaymentOption; -import it.gov.pagopa.mdb.gps.service.model.Transfer; +import it.gov.pagopa.mbd.gps.service.model.MbdPaymentOptionRequestProperties; +import it.gov.pagopa.mbd.gps.service.model.PaymentOption; +import it.gov.pagopa.mbd.gps.service.model.MbdPaymentOptionRequest; +import it.gov.pagopa.mbd.gps.service.model.MbdPaymentOptionResponse; +import it.gov.pagopa.mbd.gps.service.model.Transfer; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -23,7 +23,7 @@ @AutoConfigureMockMvc @SpringBootTest -class MdbGpsControllerTest { +class MbdGpsControllerTest { @Autowired private MockMvc mvc; @@ -33,7 +33,7 @@ class MdbGpsControllerTest { @Test void createMdbPaymentOptionTestSuccess() throws Exception { - MdbPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); MvcResult result = mvc.perform(post("/mbd/paymentOption") .content(objectMapper.writeValueAsString(request)) @@ -46,7 +46,7 @@ void createMdbPaymentOptionTestSuccess() throws Exception { assertNotNull(json); - MdbPaymentOptionResponse response = objectMapper.readValue(json, MdbPaymentOptionResponse.class); + MbdPaymentOptionResponse response = objectMapper.readValue(json, MbdPaymentOptionResponse.class); assertNotNull(response); assertNotNull(response.getPaymentOption()); @@ -76,7 +76,7 @@ void createMdbPaymentOptionTestSuccess() throws Exception { @Test void createMdbPaymentOptionTestFailAmountMissing() throws Exception { - MdbPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); request.getProperties().setAmount(null); mvc.perform(post("/mbd/paymentOption") @@ -88,7 +88,7 @@ void createMdbPaymentOptionTestFailAmountMissing() throws Exception { @Test void createMdbPaymentOptionTestFailFirstNameMissing() throws Exception { - MdbPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); request.getProperties().setFirstName(null); mvc.perform(post("/mbd/paymentOption") @@ -100,7 +100,7 @@ void createMdbPaymentOptionTestFailFirstNameMissing() throws Exception { @Test void createMdbPaymentOptionTestFailLastNameMissing() throws Exception { - MdbPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); request.getProperties().setLastName(null); mvc.perform(post("/mbd/paymentOption") @@ -112,7 +112,7 @@ void createMdbPaymentOptionTestFailLastNameMissing() throws Exception { @Test void createMdbPaymentOptionTestFailFiscalCodeMissing() throws Exception { - MdbPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); request.getProperties().setFiscalCode(null); mvc.perform(post("/mbd/paymentOption") @@ -124,7 +124,7 @@ void createMdbPaymentOptionTestFailFiscalCodeMissing() throws Exception { @Test void createMdbPaymentOptionTestFailProvincialResidenceMissing() throws Exception { - MdbPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); request.getProperties().setProvincialResidence(null); mvc.perform(post("/mbd/paymentOption") @@ -136,7 +136,7 @@ void createMdbPaymentOptionTestFailProvincialResidenceMissing() throws Exception @Test void createMdbPaymentOptionTestFailDocumentHashMissing() throws Exception { - MdbPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); request.getProperties().setDocumentHash(null); mvc.perform(post("/mbd/paymentOption") @@ -148,7 +148,7 @@ void createMdbPaymentOptionTestFailDocumentHashMissing() throws Exception { @Test void createMdbPaymentOptionTestFailDocumentHashWrongSize() throws Exception { - MdbPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); request.getProperties().setDocumentHash("asdfsdf"); mvc.perform(post("/mbd/paymentOption") @@ -158,9 +158,9 @@ void createMdbPaymentOptionTestFailDocumentHashWrongSize() throws Exception { } - private MdbPaymentOptionRequest buildMdbPaymentOptionRequest() { - return MdbPaymentOptionRequest.builder() - .properties(MdbPaymentOptionRequestProperties.builder() + private MbdPaymentOptionRequest buildMdbPaymentOptionRequest() { + return MbdPaymentOptionRequest.builder() + .properties(MbdPaymentOptionRequestProperties.builder() .amount(16L) .firstName("Mario") .lastName("Rossi") diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index d99abcb..8468f23 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -1,8 +1,8 @@ # Info -info.application.name=MDB GPS Service -info.application.artifactId=pagopa-gps-mdb-service +info.application.name=MBD GPS Service +info.application.artifactId=pagopa-gps-mbd-service info.application.version=0.0.0 -info.application.description=MDB GPS Service +info.application.description=MBD GPS Service info.properties.environment=test # Actuator From 5b8f7d29564c98e5f8f6e1c2e17caa9d7a17c8f4 Mon Sep 17 00:00:00 2001 From: giomella Date: Fri, 29 Nov 2024 18:28:44 +0100 Subject: [PATCH 09/29] [PPANTT-191] resolve project todos, configured infra, identity, helm and readme files --- .github/workflows/ci_code_review.yml | 2 +- .identity/99_variables.tf | 4 +-- .identity/env/dev/backend.tfvars | 2 +- .identity/env/dev/terraform.tfvars | 2 +- .identity/env/prod/backend.tfvars | 2 +- .identity/env/prod/terraform.tfvars | 2 +- .identity/env/uat/backend.tfvars | 2 +- .identity/env/uat/terraform.tfvars | 2 +- CODEOWNERS | 3 +- README.md | 49 ++++++++++++++++------------ docker/docker-compose.yml | 2 +- helm/values-dev.yaml | 38 ++++++++++----------- helm/values-prod.yaml | 36 ++++++++++---------- helm/values-uat.yaml | 37 ++++++++++----------- infra/04_apim_api.tf | 8 ++--- infra/99_locals.tf | 2 +- infra/env/weu-dev/backend.tfvars | 2 +- infra/env/weu-dev/terraform.tfvars | 4 +-- infra/env/weu-prod/backend.tfvars | 2 +- infra/env/weu-prod/terraform.tfvars | 4 +-- infra/env/weu-uat/backend.tfvars | 2 +- infra/env/weu-uat/terraform.tfvars | 4 +-- infra/policy/_base_policy.xml | 2 +- pom.xml | 6 ++-- sops.sh | 3 +- 25 files changed, 111 insertions(+), 111 deletions(-) diff --git a/.github/workflows/ci_code_review.yml b/.github/workflows/ci_code_review.yml index 62aab14..58e1647 100644 --- a/.github/workflows/ci_code_review.yml +++ b/.github/workflows/ci_code_review.yml @@ -18,7 +18,7 @@ on: workflow_dispatch: env: - PROJECT_KEY: # TODO + PROJECT_KEY: paogpa_pagopa-gps-mbd-service permissions: id-token: write diff --git a/.identity/99_variables.tf b/.identity/99_variables.tf index b57e1b5..4a54801 100644 --- a/.identity/99_variables.tf +++ b/.identity/99_variables.tf @@ -1,11 +1,11 @@ locals { github = { org = "pagopa" - repository = "TODO" #TODO + repository = "pagopa-mbd-gps-service" } prefix = "pagopa" - domain = "TODO" #TODO + domain = "ebollo" location_short = "weu" product = "${var.prefix}-${var.env_short}" diff --git a/.identity/env/dev/backend.tfvars b/.identity/env/dev/backend.tfvars index b5dbac8..38483ef 100644 --- a/.identity/env/dev/backend.tfvars +++ b/.identity/env/dev/backend.tfvars @@ -1,4 +1,4 @@ resource_group_name = "io-infra-rg" storage_account_name = "pagopainfraterraformdev" container_name = "azurermstate" -key = ".tfstate" # TODO +key = "pagopa-mbd-gps-service.tfstate" diff --git a/.identity/env/dev/terraform.tfvars b/.identity/env/dev/terraform.tfvars index 3345e07..4d52c59 100644 --- a/.identity/env/dev/terraform.tfvars +++ b/.identity/env/dev/terraform.tfvars @@ -6,6 +6,6 @@ tags = { CreatedBy = "Terraform" Environment = "Dev" Owner = "pagoPA" - Source = "https://github.com/pagopa/your-repository" # TODO + Source = "https://github.com/pagopa/pagopa-mbd-gps-service" CostCenter = "TS310 - PAGAMENTI & SERVIZI" } diff --git a/.identity/env/prod/backend.tfvars b/.identity/env/prod/backend.tfvars index d8d402c..e83b060 100644 --- a/.identity/env/prod/backend.tfvars +++ b/.identity/env/prod/backend.tfvars @@ -1,4 +1,4 @@ resource_group_name = "io-infra-rg" storage_account_name = "pagopainfraterraformprod" container_name = "azurermstate" -key = ".tfstate" # TODO +key = "pagopa-mbd-gps-service.tfstate" diff --git a/.identity/env/prod/terraform.tfvars b/.identity/env/prod/terraform.tfvars index ee41cf5..60ccdcd 100644 --- a/.identity/env/prod/terraform.tfvars +++ b/.identity/env/prod/terraform.tfvars @@ -6,6 +6,6 @@ tags = { CreatedBy = "Terraform" Environment = "Prod" Owner = "pagoPA" - Source = "https://github.com/pagopa/your-repository" # TODO + Source = "https://github.com/pagopa/pagopa-mbd-gps-service" CostCenter = "TS310 - PAGAMENTI & SERVIZI" } diff --git a/.identity/env/uat/backend.tfvars b/.identity/env/uat/backend.tfvars index 502eaf6..361226c 100644 --- a/.identity/env/uat/backend.tfvars +++ b/.identity/env/uat/backend.tfvars @@ -1,4 +1,4 @@ resource_group_name = "io-infra-rg" storage_account_name = "pagopainfraterraformuat" container_name = "azurermstate" -key = ".tfstate" # TODO +key = "pagopa-mbd-gps-service.tfstate" diff --git a/.identity/env/uat/terraform.tfvars b/.identity/env/uat/terraform.tfvars index 86ec8fc..b6a3a24 100644 --- a/.identity/env/uat/terraform.tfvars +++ b/.identity/env/uat/terraform.tfvars @@ -6,6 +6,6 @@ tags = { CreatedBy = "Terraform" Environment = "Uat" Owner = "pagoPA" - Source = "https://github.com/pagopa/your-repository" # TODO + Source = "https://github.com/pagopa/pagopa-mbd-gps-service" CostCenter = "TS310 - PAGAMENTI & SERVIZI" } diff --git a/CODEOWNERS b/CODEOWNERS index bac36ae..2fe107d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,4 +1,3 @@ # see https://help.github.com/en/articles/about-code-owners#example-of-a-codeowners-file -* @pagopa/pagopa-tech -# TODO: set your codeowners +* @pagopa/pagopa-team-core @alessio-cialini @svariant @gioelemella diff --git a/README.md b/README.md index 3726a09..c2da3b0 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,40 @@ -# Template for Java Spring Microservice project - -[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=TODO-set-your-id&metric=alert_status)](https://sonarcloud.io/dashboard?id=TODO-set-your-id) -[![Integration Tests](https://github.com/pagopa//actions/workflows/ci_integration_test.yml/badge.svg?branch=main)](https://github.com/pagopa//actions/workflows/ci_integration_test.yml) - -TODO: add a description - -TODO: generate a index with this tool: https://ecotrust-canada.github.io/markdown-toc/ - -TODO: resolve all the TODOs in this template +# pagoPA MBD GPS Service + +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=paogpa_pagopa-gps-mbd-service&metric=alert_status)](https://sonarcloud.io/dashboard?id=paogpa_pagopa-gps-mbd-service) +[![Integration Tests](https://github.com/pagopa/pagopa-gps-mbd-service/actions/workflows/ci_integration_test.yml/badge.svg?branch=main)](https://github.com/pagopa/pagopa-gps-mbd-service/actions/workflows/ci_integration_test.yml) + +Expose an API that will be used by GPS Payments to generate MBD payment options + +- [pagoPA MBD GPS Service](#pagopa-mbd-gps-service) + * [Api Documentation 📖](#api-documentation-) + * [Technology Stack](#technology-stack) + * [Start Project Locally 🚀](#start-project-locally-) + + [Prerequisites](#prerequisites) + + [Run docker container](#run-docker-container) + * [Develop Locally 💻](#develop-locally-) + + [Prerequisites](#prerequisites-1) + + [Run the project](#run-the-project) + + [Spring Profiles](#spring-profiles) + + [Testing 🧪](#testing-) + - [Unit testing](#unit-testing) + - [Integration testing](#integration-testing) + - [Performance testing](#performance-testing) + * [Contributors 👥](#contributors-) + + [Maintainers](#maintainers) --- ## Api Documentation 📖 -See the [OpenApi 3 here.](https://editor.swagger.io/?url=https://raw.githubusercontent.com/pagopa//main/openapi/openapi.json) +See the [OpenApi 3 here.](https://editor.swagger.io/?url=https://raw.githubusercontent.com/pagopa/pagopa-gps-mbd-service/main/openapi/openapi.json) --- ## Technology Stack -- Java 11 -- Spring Boot +- Java 17 +- Spring Boot 3 - Spring Web -- Hibernate -- JPA -- ... -- TODO --- @@ -41,8 +50,6 @@ from `./docker` directory `sh ./run_docker.sh local` -ℹ️ Note: for PagoPa ACR is required the login `az acr login -n ` - --- ## Develop Locally 💻 @@ -51,13 +58,13 @@ from `./docker` directory - git - maven -- jdk-11 +- jdk-17 ### Run the project Start the springboot application with this command: -`mvn spring-boot:run -Dspring-boot.run.profiles=local` +`mvn spring-boot:run -Dspring.profiles.active=local` ### Spring Profiles diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index d119b75..55787b9 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.8' services: app: - container_name: 'service' # TODO + container_name: 'pagopa-mbd-gps-service' image: ${image} platform: linux/amd64 build: diff --git a/helm/values-dev.yaml b/helm/values-dev.yaml index c265ccd..db567bc 100644 --- a/helm/values-dev.yaml +++ b/helm/values-dev.yaml @@ -1,9 +1,9 @@ microservice-chart: - namespace: "your-namespace" # TODO: set your AKS namespace + namespace: "ebollo" nameOverride: "" - fullnameOverride: "" + fullnameOverride: "pagopa-mbd-gps-service" image: - repository: ghcr.io/pagopa/yourname # TODO + repository: ghcr.io/pagopa/pagopa-mbd-gps-service tag: "0.0.0" pullPolicy: Always livenessProbe: @@ -29,8 +29,8 @@ microservice-chart: - 8080 ingress: create: true - host: "your.host" # TODO: set the host - path: /your-path-here/(.*) # TODO: set your path + host: "ebollo.itn.internal.dev.platform.pagopa.it" + path: /pagopa-mbd-gps-service/(.*) servicePort: 8080 serviceAccount: create: false @@ -66,26 +66,24 @@ microservice-chart: type: Utilization # Allowed types are 'Utilization' or 'AverageValue' value: "75" envConfig: - # TODO: set your name - WEBSITE_SITE_NAME: 'yourProjectName' # required to show cloud role name in application insights + APP_NAME: "pagopa-mbd-gps-service" + APP_ENVIRONMENT: "dev" + WEBSITE_SITE_NAME: 'pagopa-mbd-gps-service' # required to show cloud role name in application insights ENV: 'azure-dev' - APP_LOGGING_LEVEL: 'DEBUG' + APP_LOGGING_LEVEL: 'INFO' DEFAULT_LOGGING_LEVEL: 'INFO' CORS_CONFIGURATION: '{"origins": ["*"], "methods": ["*"]}' - - OTEL_SERVICE_NAME: # TODO - OTEL_RESOURCE_ATTRIBUTES: "deployment.environment=dev" - OTEL_EXPORTER_OTLP_ENDPOINT: "http://otel-collector.elastic-system.svc:4317" - OTEL_TRACES_EXPORTER: otlp - OTEL_METRICS_EXPORTER: otlp - OTEL_LOGS_EXPORTER: none - OTEL_TRACES_SAMPLER: "always_on" + MBD_PAYMENT_OPTION_DESCRIPTION: 'Pagamento marca da bollo digitale' + MBD_PAYMENT_OPTION_DUE_DATE_DELTA: 20 + MBD_PAYMENT_OPTION_DUE_DATE_TIME_UNIT: 'Minutes' + MBD_PAYMENT_OPTION_RETENTION_DATE_DELTA: 1 + MBD_PAYMENT_OPTION_RETENTION_DATE_TIME_UNIT: 'Hours' + MBD_TRANSFER_REMITTANCE_INFORMATION: 'Pagamento marca da bollo digitale' envSecret: # required - APPLICATIONINSIGHTS_CONNECTION_STRING: 'ai-d-connection-string' - OTEL_EXPORTER_OTLP_HEADERS: elastic-apm-secret-token + APPLICATIONINSIGHTS_CONNECTION_STRING: 'app-insight-connection-string' keyvault: - name: "pagopa-d-name-kv" #TODO + name: "pagopa-d-itn-ebollo-kv" tenantId: "7788edaf-0346-4068-9d79-c868aed15b3d" nodeSelector: { } tolerations: [ ] @@ -112,7 +110,7 @@ microservice-chart: deployment: create: true image: - repository: ghcr.io/pagopa/yourname # TODO + repository: ghcr.io/pagopa/pagopa-mbd-gps-service tag: "0.0.0" pullPolicy: Always envConfig: { } diff --git a/helm/values-prod.yaml b/helm/values-prod.yaml index 4c58544..ce72fe7 100644 --- a/helm/values-prod.yaml +++ b/helm/values-prod.yaml @@ -1,9 +1,9 @@ microservice-chart: - namespace: "your-namespace" # TODO: set your AKS namespace + namespace: "ebollo" nameOverride: "" - fullnameOverride: "" + fullnameOverride: "pagopa-mbd-gps-service" image: - repository: ghcr.io/pagopa/yourname # TODO + repository: ghcr.io/pagopa/pagopa-mbd-gps-service tag: "0.0.0" pullPolicy: Always livenessProbe: @@ -29,8 +29,8 @@ microservice-chart: - 8080 ingress: create: true - host: "your.host" # TODO: set the host - path: /your-path-here/(.*) # TODO: set your path + host: "ebollo.itn.internal.platform.pagopa.it" + path: /pagopa-mbd-gps-service/(.*) servicePort: 8080 serviceAccount: create: false @@ -66,26 +66,24 @@ microservice-chart: type: Utilization # Allowed types are 'Utilization' or 'AverageValue' value: "75" envConfig: - # TODO: set your name - WEBSITE_SITE_NAME: 'yourProjectName' # required to show cloud role name in application insights + APP_NAME: "pagopa-mbd-gps-service" + APP_ENVIRONMENT: "prod" + WEBSITE_SITE_NAME: 'pagopa-mbd-gps-service' # required to show cloud role name in application insights ENV: 'azure-prod' APP_LOGGING_LEVEL: 'INFO' DEFAULT_LOGGING_LEVEL: 'INFO' CORS_CONFIGURATION: '{"origins": ["*"], "methods": ["*"]}' - - OTEL_SERVICE_NAME: # TODO - OTEL_RESOURCE_ATTRIBUTES: "deployment.environment=prod" - OTEL_EXPORTER_OTLP_ENDPOINT: "http://otel-collector.elastic-system.svc:4317" - OTEL_TRACES_EXPORTER: otlp - OTEL_METRICS_EXPORTER: otlp - OTEL_LOGS_EXPORTER: none - OTEL_TRACES_SAMPLER: "always_on" + MBD_PAYMENT_OPTION_DESCRIPTION: 'Pagamento marca da bollo digitale' + MBD_PAYMENT_OPTION_DUE_DATE_DELTA: 20 + MBD_PAYMENT_OPTION_DUE_DATE_TIME_UNIT: 'Minutes' + MBD_PAYMENT_OPTION_RETENTION_DATE_DELTA: 1 + MBD_PAYMENT_OPTION_RETENTION_DATE_TIME_UNIT: 'Hours' + MBD_TRANSFER_REMITTANCE_INFORMATION: 'Pagamento marca da bollo digitale' envSecret: # required - APPLICATIONINSIGHTS_CONNECTION_STRING: 'ai-p-connection-string' - OTEL_EXPORTER_OTLP_HEADERS: elastic-apm-secret-token + APPLICATIONINSIGHTS_CONNECTION_STRING: 'app-insight-connection-string' keyvault: - name: "pagopa-p-name-kv" #TODO + name: "pagopa-p-itn-ebollo-kv" tenantId: "7788edaf-0346-4068-9d79-c868aed15b3d" nodeSelector: { } tolerations: [ ] @@ -112,7 +110,7 @@ microservice-chart: deployment: create: true image: - repository: ghcr.io/pagopa/yourname # TODO + repository: ghcr.io/pagopa/pagopa-mbd-gps-service tag: "0.0.0" pullPolicy: Always envConfig: { } diff --git a/helm/values-uat.yaml b/helm/values-uat.yaml index 38a99cc..26efa92 100644 --- a/helm/values-uat.yaml +++ b/helm/values-uat.yaml @@ -1,9 +1,9 @@ microservice-chart: - namespace: "your-namespace" # TODO: set your AKS namespace + namespace: "ebollo" nameOverride: "" - fullnameOverride: "" + fullnameOverride: "pagopa-mbd-gps-service" image: - repository: ghcr.io/pagopa/yourname # TODO + repository: ghcr.io/pagopa/pagopa-mbd-gps-service tag: "0.0.0" pullPolicy: Always livenessProbe: @@ -29,8 +29,8 @@ microservice-chart: - 8080 ingress: create: true - host: "your.host" # TODO: set the host - path: /your-path-here/(.*) # TODO: set your path + host: "ebollo.itn.internal.uat.platform.pagopa.it" + path: /pagopa-mbd-gps-service/(.*) servicePort: 8080 serviceAccount: create: false @@ -66,25 +66,24 @@ microservice-chart: type: Utilization # Allowed types are 'Utilization' or 'AverageValue' value: "75" envConfig: - # TODO: set your name - WEBSITE_SITE_NAME: 'yourProjectName' # required to show cloud role name in application insights + APP_NAME: "pagopa-mbd-gps-service" + APP_ENVIRONMENT: "uat" + WEBSITE_SITE_NAME: 'pagopa-mbd-gps-service' # required to show cloud role name in application insights ENV: 'azure-uat' - APP_LOGGING_LEVEL: 'DEBUG' + APP_LOGGING_LEVEL: 'INFO' DEFAULT_LOGGING_LEVEL: 'INFO' CORS_CONFIGURATION: '{"origins": ["*"], "methods": ["*"]}' - OTEL_SERVICE_NAME: # TODO - OTEL_RESOURCE_ATTRIBUTES: "deployment.environment=uat" - OTEL_EXPORTER_OTLP_ENDPOINT: "http://otel-collector.elastic-system.svc:4317" - OTEL_TRACES_EXPORTER: otlp - OTEL_METRICS_EXPORTER: otlp - OTEL_LOGS_EXPORTER: none - OTEL_TRACES_SAMPLER: "always_on" + MBD_PAYMENT_OPTION_DESCRIPTION: 'Pagamento marca da bollo digitale' + MBD_PAYMENT_OPTION_DUE_DATE_DELTA: 20 + MBD_PAYMENT_OPTION_DUE_DATE_TIME_UNIT: 'Minutes' + MBD_PAYMENT_OPTION_RETENTION_DATE_DELTA: 1 + MBD_PAYMENT_OPTION_RETENTION_DATE_TIME_UNIT: 'Hours' + MBD_TRANSFER_REMITTANCE_INFORMATION: 'Pagamento marca da bollo digitale' envSecret: # required - APPLICATIONINSIGHTS_CONNECTION_STRING: 'ai-u-connection-string' - OTEL_EXPORTER_OTLP_HEADERS: elastic-apm-secret-token + APPLICATIONINSIGHTS_CONNECTION_STRING: 'app-insight-connection-string' keyvault: - name: "pagopa-u-name-kv" #TODO + name: "pagopa-u-itn-ebollo-kv" tenantId: "7788edaf-0346-4068-9d79-c868aed15b3d" nodeSelector: { } tolerations: [ ] @@ -111,7 +110,7 @@ microservice-chart: deployment: create: true image: - repository: ghcr.io/pagopa/yourname # TODO + repository: ghcr.io/pagopa/pagopa-mbd-gps-service tag: "0.0.0" pullPolicy: Always envConfig: { } diff --git a/infra/04_apim_api.tf b/infra/04_apim_api.tf index b24ae4d..01096a9 100644 --- a/infra/04_apim_api.tf +++ b/infra/04_apim_api.tf @@ -1,9 +1,9 @@ locals { - repo_name = "TODO" # TODO add the name of the repository + repo_name = "pagopa-gps-mbd-service" - display_name = "TODO" # TODO - description = "TODO" # TODO - path = "TODO" # TODO add your base path + display_name = "MBD GPS Service" + description = "API for MBD GPS Service" + path = "pagopa-mbd-gps-service" host = "api.${var.apim_dns_zone_prefix}.${var.external_domain}" hostname = var.hostname diff --git a/infra/99_locals.tf b/infra/99_locals.tf index 5ed42d0..0ac3333 100644 --- a/infra/99_locals.tf +++ b/infra/99_locals.tf @@ -4,7 +4,7 @@ locals { apim = { name = "${local.product}-apim" rg = "${local.product}-api-rg" - product_id = "TODO" # TODO product id to import from pagopa-infra + product_id = "ebollo-gps-service" } } diff --git a/infra/env/weu-dev/backend.tfvars b/infra/env/weu-dev/backend.tfvars index 619395b..d3a438f 100644 --- a/infra/env/weu-dev/backend.tfvars +++ b/infra/env/weu-dev/backend.tfvars @@ -1,4 +1,4 @@ resource_group_name = "io-infra-rg" storage_account_name = "pagopainfraterraformdev" container_name = "azurermstate" -key = ".infra.tfstate" # TODO +key = "pagopa-gps-mbd-service.infra.tfstate" diff --git a/infra/env/weu-dev/terraform.tfvars b/infra/env/weu-dev/terraform.tfvars index 63a0705..7e2fa0f 100644 --- a/infra/env/weu-dev/terraform.tfvars +++ b/infra/env/weu-dev/terraform.tfvars @@ -6,10 +6,10 @@ tags = { CreatedBy = "Terraform" Environment = "Dev" Owner = "pagoPA" - Source = "https://github.com/pagopa/your-repository" # TODO + Source = "https://github.com/pagopa/pagopa-gps-mbd-service" CostCenter = "TS310 - PAGAMENTI & SERVIZI" } apim_dns_zone_prefix = "dev.platform" external_domain = "pagopa.it" -hostname = "weudev..internal.dev.platform.pagopa.it" # TODO +hostname = "weudev.gps.internal.dev.platform.pagopa.it" diff --git a/infra/env/weu-prod/backend.tfvars b/infra/env/weu-prod/backend.tfvars index dac1727..39d1934 100644 --- a/infra/env/weu-prod/backend.tfvars +++ b/infra/env/weu-prod/backend.tfvars @@ -1,4 +1,4 @@ resource_group_name = "io-infra-rg" storage_account_name = "pagopainfraterraformprod" container_name = "azurermstate" -key = ".infra.tfstate" # TODO +key = "pagopa-gps-mbd-service.infra.tfstate" diff --git a/infra/env/weu-prod/terraform.tfvars b/infra/env/weu-prod/terraform.tfvars index 77f85af..9e3614c 100644 --- a/infra/env/weu-prod/terraform.tfvars +++ b/infra/env/weu-prod/terraform.tfvars @@ -6,10 +6,10 @@ tags = { CreatedBy = "Terraform" Environment = "Prod" Owner = "pagoPA" - Source = "https://github.com/pagopa/your-repository" # TODO + Source = "https://github.com/pagopa/pagopa-gps-mbd-service" CostCenter = "TS310 - PAGAMENTI & SERVIZI" } apim_dns_zone_prefix = "platform" external_domain = "pagopa.it" -hostname = "weuprod..internal.platform.pagopa.it" # TODO +hostname = "weuprod.gps.internal.platform.pagopa.it" diff --git a/infra/env/weu-uat/backend.tfvars b/infra/env/weu-uat/backend.tfvars index 6f406b1..fac072a 100644 --- a/infra/env/weu-uat/backend.tfvars +++ b/infra/env/weu-uat/backend.tfvars @@ -1,4 +1,4 @@ resource_group_name = "io-infra-rg" storage_account_name = "pagopainfraterraformuat" container_name = "azurermstate" -key = ".infra.tfstate" # TODO +key = "pagopa-gps-mbd-service.infra.tfstate" diff --git a/infra/env/weu-uat/terraform.tfvars b/infra/env/weu-uat/terraform.tfvars index e8160f1..6a6eb1a 100644 --- a/infra/env/weu-uat/terraform.tfvars +++ b/infra/env/weu-uat/terraform.tfvars @@ -6,10 +6,10 @@ tags = { CreatedBy = "Terraform" Environment = "Uat" Owner = "pagoPA" - Source = "https://github.com/pagopa/your-repository" # TODO + Source = "https://github.com/pagopa/pagopa-gps-mbd-service" CostCenter = "TS310 - PAGAMENTI & SERVIZI" } apim_dns_zone_prefix = "uat.platform" external_domain = "pagopa.it" -hostname = "weuuat..internal.uat.platform.pagopa.it" # TODO +hostname = "weuuat.gps.internal.uat.platform.pagopa.it" diff --git a/infra/policy/_base_policy.xml b/infra/policy/_base_policy.xml index e3b583c..8f90c81 100644 --- a/infra/policy/_base_policy.xml +++ b/infra/policy/_base_policy.xml @@ -1,7 +1,7 @@ - + diff --git a/pom.xml b/pom.xml index 234765f..abaaad9 100644 --- a/pom.xml +++ b/pom.xml @@ -11,10 +11,10 @@ it.gov.pagopa - pagopa-gps-mdb-service + pagopa-gps-mbd-service 0.0.0 - MDB GPS Service - MDB GPS Service + MBD GPS Service + MBD GPS Service 17 diff --git a/sops.sh b/sops.sh index dbf1ec7..bc35456 100755 --- a/sops.sh +++ b/sops.sh @@ -54,8 +54,7 @@ main() { env_short=$(echo "$environment" | cut -c1) - # TODO set your kv - azure_kv_url=$(az keyvault key show --name pagopa-"$env_short"-TODO-sops-key --vault-name pagopa-"$env_short"-TODO-kv --query key.kid | sed 's/"//g') + azure_kv_url=$(az keyvault key show --name pagopa-"$env_short"-ebollo-sops-key --vault-name pagopa-"$env_short"-ebollo-kv --query key.kid | sed 's/"//g') if [ "$action" == "enc" ]; then sops --encrypt --azure-kv "$azure_kv_url" --input-type dotenv --output-type dotenv ./"$filepath" > ./"$filepath".encrypted From af03be9e1f082382fda89b0610d3fdc52de2dec5 Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 2 Dec 2024 12:28:56 +0100 Subject: [PATCH 10/29] [PPANTT-191] fix --- .../it/gov/pagopa/mbd/gps/service/config/ResponseValidator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/config/ResponseValidator.java b/src/main/java/it/gov/pagopa/mbd/gps/service/config/ResponseValidator.java index ccfa67a..2a0713b 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/config/ResponseValidator.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/config/ResponseValidator.java @@ -26,7 +26,7 @@ public ResponseValidator(Validator validator) { } /** - * This method validates the response annotated with the {@link jakarta.validation.Constraint} + * This method validates the response annotated with the {@link jakarta.validation.constraints} * * @param joinPoint not used * @param result the response to validate From 0c387fdebaa4ee76e5be210a8d598e93404d3e31 Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 2 Dec 2024 12:45:13 +0100 Subject: [PATCH 11/29] [PPANTT-191] updated cd_deploy_with_github_runner gha to use self-hosted-job instead of runner --- .../cd_deploy_with_github_runner.yml | 42 +------------------ 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/.github/workflows/cd_deploy_with_github_runner.yml b/.github/workflows/cd_deploy_with_github_runner.yml index 9157f6e..0a66dc8 100644 --- a/.github/workflows/cd_deploy_with_github_runner.yml +++ b/.github/workflows/cd_deploy_with_github_runner.yml @@ -44,30 +44,9 @@ permissions: contents: read jobs: - create_runner: - name: Create Runner - runs-on: ubuntu-22.04 - environment: - name: ${{ inputs.environment }} - outputs: - runner_name: ${{ steps.create_github_runner.outputs.runner_name }} - steps: - - name: Create GitHub Runner - id: create_github_runner - # from https://github.com/pagopa/eng-github-actions-iac-template/tree/main/azure/github-self-hosted-runner-azure-create-action - uses: pagopa/eng-github-actions-iac-template/azure/github-self-hosted-runner-azure-create-action@main - with: - client_id: ${{ secrets.CLIENT_ID }} - tenant_id: ${{ secrets.TENANT_ID }} - subscription_id: ${{ secrets.SUBSCRIPTION_ID }} - container_app_environment_name: ${{ vars.CONTAINER_APP_ENVIRONMENT_NAME }} - resource_group_name: ${{ vars.CONTAINER_APP_ENVIRONMENT_RESOURCE_GROUP_NAME }} # RG of the runner - pat_token: ${{ secrets.BOT_TOKEN_GITHUB }} - self_hosted_runner_image_tag: "latest" - deploy: needs: [ create_runner ] - runs-on: [ self-hosted, "${{ needs.create_runner.outputs.runner_name }}" ] + runs-on: [ self-hosted-job ] name: Deploy on AKS environment: ${{ inputs.environment }} steps: @@ -93,25 +72,6 @@ jobs: run: | helm uninstall ${{ env.APP_NAME }}${{inputs.suffix_name}} -n ${{ vars.NAMESPACE }} - cleanup_runner: - name: Cleanup Runner - needs: [ create_runner, deploy ] - if: ${{ success() || failure() }} - runs-on: ubuntu-22.04 - environment: ${{ inputs.environment }} - steps: - - name: Cleanup GitHub Runner - id: cleanup_github_runner - # from https://github.com/pagopa/eng-github-actions-iac-template/tree/main/azure/github-self-hosted-runner-azure-cleanup-action - uses: pagopa/eng-github-actions-iac-template/azure/github-self-hosted-runner-azure-cleanup-action@main - with: - client_id: ${{ secrets.CLIENT_ID }} - tenant_id: ${{ secrets.TENANT_ID }} - subscription_id: ${{ secrets.SUBSCRIPTION_ID }} - resource_group_name: ${{ vars.CONTAINER_APP_ENVIRONMENT_RESOURCE_GROUP_NAME }} - runner_name: ${{ needs.create_runner.outputs.runner_name }} - pat_token: ${{ secrets.BOT_TOKEN_GITHUB }} - update_openapi: needs: [ deploy ] runs-on: ubuntu-latest From 02cc8f4b4abd23767e2c2f69f82b607ab8e9ee50 Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 2 Dec 2024 13:00:15 +0100 Subject: [PATCH 12/29] [PPANTT-191] bump chart version to 7.1.1 and configured workload identity --- .github/workflows/cd_deploy_with_github_runner.yml | 2 +- .identity/00_data.tf | 5 +++++ .identity/01_github_environment.tf | 1 + helm/Chart.yaml | 2 +- helm/values-dev.yaml | 8 +++++--- helm/values-prod.yaml | 8 +++++--- helm/values-uat.yaml | 8 +++++--- 7 files changed, 23 insertions(+), 11 deletions(-) diff --git a/.github/workflows/cd_deploy_with_github_runner.yml b/.github/workflows/cd_deploy_with_github_runner.yml index 0a66dc8..1424aad 100644 --- a/.github/workflows/cd_deploy_with_github_runner.yml +++ b/.github/workflows/cd_deploy_with_github_runner.yml @@ -63,7 +63,7 @@ jobs: cluster_name: ${{ vars.CLUSTER_NAME }} resource_group: ${{ vars.CLUSTER_RESOURCE_GROUP }} app_name: ${{ env.APP_NAME }}${{inputs.suffix_name}} - helm_upgrade_options: "--debug ${{inputs.helm_options}}" + helm_upgrade_options: '--debug --set microservice-chart.azure.workloadIdentityClientId=${{env.WORKLOAD_IDENTITY_ID}} ${{inputs.helm_options}}' timeout: '10m0s' - name: Remove deployment diff --git a/.identity/00_data.tf b/.identity/00_data.tf index 21a1449..8d9fa54 100644 --- a/.identity/00_data.tf +++ b/.identity/00_data.tf @@ -57,3 +57,8 @@ data "azurerm_key_vault_secret" "key_vault_integration_test_subkey" { name = "integration-test-subkey" key_vault_id = data.azurerm_key_vault.key_vault.id } + +data "azurerm_user_assigned_identity" "workload_identity_clientid" { + name = "ebollo-workload-identity" + resource_group_name = "pagopa-${var.env_short}-itn-${var.env}-aks-rg" +} \ No newline at end of file diff --git a/.identity/01_github_environment.tf b/.identity/01_github_environment.tf index d570189..d084ccb 100644 --- a/.identity/01_github_environment.tf +++ b/.identity/01_github_environment.tf @@ -32,6 +32,7 @@ locals { "CLUSTER_NAME" : local.aks_cluster.name, "CLUSTER_RESOURCE_GROUP" : local.aks_cluster.resource_group_name, "NAMESPACE" : local.domain, + "WORKLOAD_IDENTITY_ID": data.azurerm_user_assigned_identity.workload_identity_clientid.client_id } repo_secrets = { "SONAR_TOKEN" : data.azurerm_key_vault_secret.key_vault_sonar.value, diff --git a/helm/Chart.yaml b/helm/Chart.yaml index 2f15c6e..bceb4e7 100644 --- a/helm/Chart.yaml +++ b/helm/Chart.yaml @@ -6,5 +6,5 @@ version: 0.0.0 appVersion: 0.0.0 dependencies: - name: microservice-chart - version: 5.9.0 + version: 7.1.1 repository: "https://pagopa.github.io/aks-microservice-chart-blueprint" diff --git a/helm/values-dev.yaml b/helm/values-dev.yaml index db567bc..362f6e7 100644 --- a/helm/values-dev.yaml +++ b/helm/values-dev.yaml @@ -7,6 +7,7 @@ microservice-chart: tag: "0.0.0" pullPolicy: Always livenessProbe: + handlerType: httpGet httpGet: path: /actuator/health/liveness port: 8080 @@ -14,6 +15,7 @@ microservice-chart: failureThreshold: 6 periodSeconds: 10 readinessProbe: + handlerType: httpGet httpGet: path: /actuator/health/readiness port: 8080 @@ -33,9 +35,9 @@ microservice-chart: path: /pagopa-mbd-gps-service/(.*) servicePort: 8080 serviceAccount: - create: false - annotations: { } - name: "" + name: "ebollo-workload-identity" + azure: + workloadIdentityClientId: podAnnotations: { } podSecurityContext: seccompProfile: diff --git a/helm/values-prod.yaml b/helm/values-prod.yaml index ce72fe7..ede93db 100644 --- a/helm/values-prod.yaml +++ b/helm/values-prod.yaml @@ -7,6 +7,7 @@ microservice-chart: tag: "0.0.0" pullPolicy: Always livenessProbe: + handlerType: httpGet httpGet: path: /actuator/health/liveness port: 8080 @@ -14,6 +15,7 @@ microservice-chart: failureThreshold: 6 periodSeconds: 10 readinessProbe: + handlerType: httpGet httpGet: path: /actuator/health/readiness port: 8080 @@ -33,9 +35,9 @@ microservice-chart: path: /pagopa-mbd-gps-service/(.*) servicePort: 8080 serviceAccount: - create: false - annotations: { } - name: "" + name: "ebollo-workload-identity" + azure: + workloadIdentityClientId: podAnnotations: { } podSecurityContext: seccompProfile: diff --git a/helm/values-uat.yaml b/helm/values-uat.yaml index 26efa92..894b36a 100644 --- a/helm/values-uat.yaml +++ b/helm/values-uat.yaml @@ -7,6 +7,7 @@ microservice-chart: tag: "0.0.0" pullPolicy: Always livenessProbe: + handlerType: httpGet httpGet: path: /actuator/health/liveness port: 8080 @@ -14,6 +15,7 @@ microservice-chart: failureThreshold: 6 periodSeconds: 10 readinessProbe: + handlerType: httpGet httpGet: path: /actuator/health/readiness port: 8080 @@ -33,9 +35,9 @@ microservice-chart: path: /pagopa-mbd-gps-service/(.*) servicePort: 8080 serviceAccount: - create: false - annotations: { } - name: "" + name: "ebollo-workload-identity" + azure: + workloadIdentityClientId: podAnnotations: { } podSecurityContext: seccompProfile: From 998e8e77582c52076faca6a55f43e1e3ea529579 Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 2 Dec 2024 13:00:33 +0100 Subject: [PATCH 13/29] [PPANTT-191] added pod affinity in prod helm --- helm/values-prod.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/helm/values-prod.yaml b/helm/values-prod.yaml index ede93db..433c200 100644 --- a/helm/values-prod.yaml +++ b/helm/values-prod.yaml @@ -98,6 +98,15 @@ microservice-chart: operator: In values: - user + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchLabels: + app.kubernetes.io/instance: pagopa-mbd-gps-service + namespaces: [ "ebollo" ] + topologyKey: topology.kubernetes.io/zone canaryDelivery: create: true ingress: From 83cc121bb1a4071f2207ce5c4041003def49830d Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 2 Dec 2024 15:32:48 +0100 Subject: [PATCH 14/29] [PPANTT-191] fix deploy gha --- .github/workflows/cd_deploy_with_github_runner.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cd_deploy_with_github_runner.yml b/.github/workflows/cd_deploy_with_github_runner.yml index 1424aad..18abee6 100644 --- a/.github/workflows/cd_deploy_with_github_runner.yml +++ b/.github/workflows/cd_deploy_with_github_runner.yml @@ -63,7 +63,7 @@ jobs: cluster_name: ${{ vars.CLUSTER_NAME }} resource_group: ${{ vars.CLUSTER_RESOURCE_GROUP }} app_name: ${{ env.APP_NAME }}${{inputs.suffix_name}} - helm_upgrade_options: '--debug --set microservice-chart.azure.workloadIdentityClientId=${{env.WORKLOAD_IDENTITY_ID}} ${{inputs.helm_options}}' + helm_upgrade_options: '--debug --set microservice-chart.azure.workloadIdentityClientId=${{vars.WORKLOAD_IDENTITY_ID}} ${{inputs.helm_options}}' timeout: '10m0s' - name: Remove deployment From 470879ad8df9478f534770a45a849441fea81a81 Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 2 Dec 2024 17:08:33 +0100 Subject: [PATCH 15/29] [PPANTT-191] bump sonar plugin version and added maven-compiler-plugin --- pom.xml | 254 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 131 insertions(+), 123 deletions(-) diff --git a/pom.xml b/pom.xml index abaaad9..96e4ccf 100644 --- a/pom.xml +++ b/pom.xml @@ -1,137 +1,145 @@ - 4.0.0 + xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.2.3 - + + org.springframework.boot + spring-boot-starter-parent + 3.2.3 + - it.gov.pagopa - pagopa-gps-mbd-service - 0.0.0 - MBD GPS Service - MBD GPS Service + it.gov.pagopa + pagopa-gps-mbd-service + 0.0.0 + MBD GPS Service + MBD GPS Service - - 17 - + + 17 + - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-validation - + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-validation + - - - org.springframework.boot - spring-boot-devtools - runtime - true - - - org.springframework.boot - spring-boot-configuration-processor - true - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-starter-aop - - - org.springframework.boot - spring-boot-starter-actuator - + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-aop + + + org.springframework.boot + spring-boot-starter-actuator + - - - org.springdoc - springdoc-openapi-starter-webmvc-ui - 2.3.0 - + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.3.0 + - - - org.modelmapper - modelmapper - 3.1.0 - - - org.projectlombok - lombok - true - - - co.elastic.logging - logback-ecs-encoder - 1.5.0 - - + + + org.modelmapper + modelmapper + 3.1.0 + + + org.projectlombok + lombok + true + + + co.elastic.logging + logback-ecs-encoder + 1.5.0 + + - - - - org.springframework.boot - spring-boot-maven-plugin - + + + + org.springframework.boot + spring-boot-maven-plugin + - - org.jacoco - jacoco-maven-plugin - 0.8.7 - - - - - - - - prepare-agent - - - - report - test - - report - - - - - - org.sonarsource.scanner.maven - sonar-maven-plugin - 3.3.0.603 - - - verify - - sonar - - - - - - - - src/test/resources - true - - - + + org.jacoco + jacoco-maven-plugin + 0.8.7 + + + + + + + + prepare-agent + + + + report + test + + report + + + + + + org.sonarsource.scanner.maven + sonar-maven-plugin + 3.7.0.1746 + + + verify + + sonar + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 17 + 17 + + + + + + src/test/resources + true + + + From 66dffdde9693914061748ea8a029682bf30b62dd Mon Sep 17 00:00:00 2001 From: giomella Date: Mon, 2 Dec 2024 17:14:26 +0100 Subject: [PATCH 16/29] [PPANTT-191] fix --- .github/workflows/ci_code_review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_code_review.yml b/.github/workflows/ci_code_review.yml index 58e1647..108f708 100644 --- a/.github/workflows/ci_code_review.yml +++ b/.github/workflows/ci_code_review.yml @@ -18,7 +18,7 @@ on: workflow_dispatch: env: - PROJECT_KEY: paogpa_pagopa-gps-mbd-service + PROJECT_KEY: pagopa_pagopa-gps-mbd-service permissions: id-token: write From 6bb9c0100442fdb786335957cfac5d135675f103 Mon Sep 17 00:00:00 2001 From: giomella Date: Tue, 3 Dec 2024 11:34:59 +0100 Subject: [PATCH 17/29] [PPANTT-191] fix --- .github/workflows/cd_deploy_with_github_runner.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/cd_deploy_with_github_runner.yml b/.github/workflows/cd_deploy_with_github_runner.yml index 18abee6..20ed817 100644 --- a/.github/workflows/cd_deploy_with_github_runner.yml +++ b/.github/workflows/cd_deploy_with_github_runner.yml @@ -45,8 +45,7 @@ permissions: jobs: deploy: - needs: [ create_runner ] - runs-on: [ self-hosted-job ] + runs-on: [ self-hosted-job, "${{ inputs.environment }}" ] name: Deploy on AKS environment: ${{ inputs.environment }} steps: From 1c4c54d3dfc731b0256c9845e3cd3ee126f76c25 Mon Sep 17 00:00:00 2001 From: giomella Date: Wed, 4 Dec 2024 12:47:41 +0100 Subject: [PATCH 18/29] [PPANTT-191] fix --- infra/env/{weu-dev => itn-dev}/backend.ini | 0 infra/env/{weu-dev => itn-dev}/backend.tfvars | 0 infra/env/{weu-dev => itn-dev}/terraform.tfvars | 6 +++--- infra/env/{weu-prod => itn-prod}/backend.ini | 0 infra/env/{weu-prod => itn-prod}/backend.tfvars | 0 infra/env/{weu-prod => itn-prod}/terraform.tfvars | 6 +++--- infra/env/{weu-uat => itn-uat}/backend.ini | 0 infra/env/{weu-uat => itn-uat}/backend.tfvars | 0 infra/env/{weu-uat => itn-uat}/terraform.tfvars | 6 +++--- 9 files changed, 9 insertions(+), 9 deletions(-) rename infra/env/{weu-dev => itn-dev}/backend.ini (100%) rename infra/env/{weu-dev => itn-dev}/backend.tfvars (100%) rename infra/env/{weu-dev => itn-dev}/terraform.tfvars (61%) rename infra/env/{weu-prod => itn-prod}/backend.ini (100%) rename infra/env/{weu-prod => itn-prod}/backend.tfvars (100%) rename infra/env/{weu-prod => itn-prod}/terraform.tfvars (63%) rename infra/env/{weu-uat => itn-uat}/backend.ini (100%) rename infra/env/{weu-uat => itn-uat}/backend.tfvars (100%) rename infra/env/{weu-uat => itn-uat}/terraform.tfvars (61%) diff --git a/infra/env/weu-dev/backend.ini b/infra/env/itn-dev/backend.ini similarity index 100% rename from infra/env/weu-dev/backend.ini rename to infra/env/itn-dev/backend.ini diff --git a/infra/env/weu-dev/backend.tfvars b/infra/env/itn-dev/backend.tfvars similarity index 100% rename from infra/env/weu-dev/backend.tfvars rename to infra/env/itn-dev/backend.tfvars diff --git a/infra/env/weu-dev/terraform.tfvars b/infra/env/itn-dev/terraform.tfvars similarity index 61% rename from infra/env/weu-dev/terraform.tfvars rename to infra/env/itn-dev/terraform.tfvars index 7e2fa0f..e98f40b 100644 --- a/infra/env/weu-dev/terraform.tfvars +++ b/infra/env/itn-dev/terraform.tfvars @@ -10,6 +10,6 @@ tags = { CostCenter = "TS310 - PAGAMENTI & SERVIZI" } -apim_dns_zone_prefix = "dev.platform" -external_domain = "pagopa.it" -hostname = "weudev.gps.internal.dev.platform.pagopa.it" +apim_dns_zone_prefix = "dev.platform" +external_domain = "pagopa.it" +hostname = "ebollo.itn.internal.dev.platform.pagopa.it" diff --git a/infra/env/weu-prod/backend.ini b/infra/env/itn-prod/backend.ini similarity index 100% rename from infra/env/weu-prod/backend.ini rename to infra/env/itn-prod/backend.ini diff --git a/infra/env/weu-prod/backend.tfvars b/infra/env/itn-prod/backend.tfvars similarity index 100% rename from infra/env/weu-prod/backend.tfvars rename to infra/env/itn-prod/backend.tfvars diff --git a/infra/env/weu-prod/terraform.tfvars b/infra/env/itn-prod/terraform.tfvars similarity index 63% rename from infra/env/weu-prod/terraform.tfvars rename to infra/env/itn-prod/terraform.tfvars index 9e3614c..c03a753 100644 --- a/infra/env/weu-prod/terraform.tfvars +++ b/infra/env/itn-prod/terraform.tfvars @@ -10,6 +10,6 @@ tags = { CostCenter = "TS310 - PAGAMENTI & SERVIZI" } -apim_dns_zone_prefix = "platform" -external_domain = "pagopa.it" -hostname = "weuprod.gps.internal.platform.pagopa.it" +apim_dns_zone_prefix = "platform" +external_domain = "pagopa.it" +hostname = "ebollo.itn.internal.platform.pagopa.it" diff --git a/infra/env/weu-uat/backend.ini b/infra/env/itn-uat/backend.ini similarity index 100% rename from infra/env/weu-uat/backend.ini rename to infra/env/itn-uat/backend.ini diff --git a/infra/env/weu-uat/backend.tfvars b/infra/env/itn-uat/backend.tfvars similarity index 100% rename from infra/env/weu-uat/backend.tfvars rename to infra/env/itn-uat/backend.tfvars diff --git a/infra/env/weu-uat/terraform.tfvars b/infra/env/itn-uat/terraform.tfvars similarity index 61% rename from infra/env/weu-uat/terraform.tfvars rename to infra/env/itn-uat/terraform.tfvars index 6a6eb1a..7b5cb1d 100644 --- a/infra/env/weu-uat/terraform.tfvars +++ b/infra/env/itn-uat/terraform.tfvars @@ -10,6 +10,6 @@ tags = { CostCenter = "TS310 - PAGAMENTI & SERVIZI" } -apim_dns_zone_prefix = "uat.platform" -external_domain = "pagopa.it" -hostname = "weuuat.gps.internal.uat.platform.pagopa.it" +apim_dns_zone_prefix = "uat.platform" +external_domain = "pagopa.it" +hostname = "ebollo.itn.internal.uat.platform.pagopa.it" From 2800678d170f8279d2a53c2e832459d99ebd5a13 Mon Sep 17 00:00:00 2001 From: pasqualespica Date: Wed, 4 Dec 2024 12:59:02 +0100 Subject: [PATCH 19/29] fix apply identity and repo name --- .identity/.terraform.lock.hcl | 64 +++++ .identity/00_data.tf | 4 +- .identity/99_variables.tf | 2 +- .identity/env/dev/backend.tfvars | 2 +- .identity/env/dev/terraform.tfvars | 2 +- .identity/env/prod/backend.tfvars | 2 +- .identity/env/prod/terraform.tfvars | 2 +- .identity/env/uat/backend.tfvars | 2 +- .identity/env/uat/terraform.tfvars | 2 +- README.md | 2 +- docker/docker-compose.yml | 2 +- helm/values-dev.yaml | 12 +- helm/values-prod.yaml | 14 +- helm/values-uat.yaml | 12 +- infra/04_apim_api.tf | 2 +- infra/policy/_base_policy.xml | 2 +- openapi/openapi.json | 2 +- .../mbd/gps/service/config/OpenApiConfig.java | 228 +++++++++--------- 18 files changed, 212 insertions(+), 146 deletions(-) create mode 100644 .identity/.terraform.lock.hcl diff --git a/.identity/.terraform.lock.hcl b/.identity/.terraform.lock.hcl new file mode 100644 index 0000000..e659e8d --- /dev/null +++ b/.identity/.terraform.lock.hcl @@ -0,0 +1,64 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/azuread" { + version = "2.30.0" + constraints = "2.30.0" + hashes = [ + "h1:Uw4TcmJBEJ71h+oCwwidlkk5jFpyFRDPAFCMs/bT/cw=", + "zh:1c3e89cf19118fc07d7b04257251fc9897e722c16e0a0df7b07fcd261f8c12e7", + "zh:2e62c193030e04ebb10cc0526119cf69824bf2d7e4ea5a2f45bd5d5fb7221d36", + "zh:2f3c7a35257332d68b778cefc5201a5f044e4914dd03794a4da662ddfe756483", + "zh:35d0d3a1b58fdb8b8c4462d6b7e7016042da43ea9cc734ce897f52a73407d9b0", + "zh:47ede0cd0206ec953d40bf4a80aa6e59af64e26cbbd877614ac424533dbb693b", + "zh:48c190307d4d42ea67c9b8cc544025024753f46cef6ea64db84735e7055a72da", + "zh:6fff9b2c6a962252a70a15b400147789ab369b35a781e9d21cce3804b04d29af", + "zh:7646980cf3438bff29c91ffedb74458febbb00a996638751fbd204ab1c628c9b", + "zh:77aa2fa7ca6d5446afa71d4ff83cb87b70a2f3b72110fc442c339e8e710b2928", + "zh:e20b2b2c37175b89dd0db058a096544d448032e28e3b56e2db368343533a9684", + "zh:eab175b1dfe9865ad9404dccb6d5542899f8c435095aa7c679314b811c717ce7", + "zh:efc862bd78c55d2ff089729e2a34c1831ab4b0644fc11b36ee4ebed00a4797ba", + ] +} + +provider "registry.terraform.io/hashicorp/azurerm" { + version = "3.45.0" + constraints = "3.45.0" + hashes = [ + "h1:VQWxV5+qelZeUCjpdLvZ7iAom4RvG+fVVgK6ELvw/cs=", + "zh:04c5dbb8845366ce5eb0dc2d55e151270cc2c0ace20993867fdae9af43b953ad", + "zh:2589585da615ccae341400d45d672ee3fae413fdd88449b5befeff12a85a44b2", + "zh:603869ed98fff5d9bf841a51afd9e06b628533c59356c8433aef4b15df63f5f7", + "zh:853fecab9c987b6772c8d9aa10362675f6c626b60ebc7118aa33ce91366fcc38", + "zh:979848c45e8e058862c36ba3a661457f7c81ef26ebb6634f479600de9c203d65", + "zh:9b512c8588ecc9c1b803b746a3a8517422561a918f0dfb0faaa707ed53ef1760", + "zh:a9601ffb58043426bcff1220662d6d137f0b2857a24f2dcf180aeac2c9cea688", + "zh:d52d2652328f0ed3ba202561d88cb9f43c174edbfaab1abf69f772125dbfe15e", + "zh:d92d91ca597c47f575bf3ae129f4b723be9b7dcb71b906ec6ec740fac29b1aaa", + "zh:ded73b730e4197b70fda9e83447c119f92f75dc37be3ff2ed45730c8f0348c28", + "zh:ec37ac332d50f8ca5827f97198346b0f8ecbf470e2e3ba1e027bb389d826b902", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + ] +} + +provider "registry.terraform.io/integrations/github" { + version = "5.18.3" + constraints = "5.18.3" + hashes = [ + "h1:WbZvLB2qXKVoh4BvOOwFfEds+SZQrkINfSAWPnWFxGo=", + "zh:050b37d96628cb7451137755929ca8d21ea546bc46d11a715652584070e83ff2", + "zh:053051061f1b7f7673b0ceffac1f239ba28b0e5b375999206fd39976e85d9f2b", + "zh:0c300a977ca66d0347ed62bb116fd8fc9abb376a554d4c192d14f3ea71c83500", + "zh:1d5a1a5243eba78819d2f92ff2d504ebf9a9008a6670fb5f5660f44eb6a156d8", + "zh:a13ac15d251ebf4e7dc40acb0e40df066f443f4c7799186a29e2e44addc7d8e7", + "zh:a316d94b885953c036ebc9fba64a23da93974746bc3ac9d207462a6f02d44540", + "zh:a658a00373bff5979cc227052c693cbde8ca4c8f9fef1bc8094a3516f2e2a96d", + "zh:a7bfc6ad8465d5dc11b6f19d6805364de87fffe27622bb4f37da2319bb1c4956", + "zh:d7379a76861f1a6bfc36eca7a20f1f477711247563b105744d69d7bd1f365fad", + "zh:de1cd959fd4821248e8d21570601193408648474e74f49597f1d0c43185a4ab7", + "zh:e0b281240dd6f2aa405b2d6fe329bc15ab877161affe163fb150d1efca2fccdb", + "zh:e372c171358757a983d7aa878abfd05a84484fb4d22167e45c9c1267e78ed060", + "zh:f6d3116526030b3f6905f530cd6c04b23d42890d973fa2abe10ce9c89cb1db80", + "zh:f99eec731e03cc6a28996c875bd435887cd7ea75ec07cc77b9e768bb12da2227", + ] +} diff --git a/.identity/00_data.tf b/.identity/00_data.tf index 8d9fa54..6df6058 100644 --- a/.identity/00_data.tf +++ b/.identity/00_data.tf @@ -34,8 +34,8 @@ data "azurerm_user_assigned_identity" "identity_pr_01" { } data "azurerm_key_vault" "domain_key_vault" { - name = "pagopa-${var.env_short}-${local.domain}-kv" - resource_group_name = "pagopa-${var.env_short}-${local.domain}-sec-rg" + name = "pagopa-${var.env_short}-itn-${local.domain}-kv" + resource_group_name = "pagopa-${var.env_short}-itn-${local.domain}-sec-rg" } data "azurerm_key_vault_secret" "key_vault_sonar" { diff --git a/.identity/99_variables.tf b/.identity/99_variables.tf index 4a54801..d5acdff 100644 --- a/.identity/99_variables.tf +++ b/.identity/99_variables.tf @@ -1,7 +1,7 @@ locals { github = { org = "pagopa" - repository = "pagopa-mbd-gps-service" + repository = "pagopa-gps-mbd-service" } prefix = "pagopa" diff --git a/.identity/env/dev/backend.tfvars b/.identity/env/dev/backend.tfvars index 38483ef..5cde786 100644 --- a/.identity/env/dev/backend.tfvars +++ b/.identity/env/dev/backend.tfvars @@ -1,4 +1,4 @@ resource_group_name = "io-infra-rg" storage_account_name = "pagopainfraterraformdev" container_name = "azurermstate" -key = "pagopa-mbd-gps-service.tfstate" +key = "pagopa-gps-mbd-service.tfstate" diff --git a/.identity/env/dev/terraform.tfvars b/.identity/env/dev/terraform.tfvars index 4d52c59..d9a57ae 100644 --- a/.identity/env/dev/terraform.tfvars +++ b/.identity/env/dev/terraform.tfvars @@ -6,6 +6,6 @@ tags = { CreatedBy = "Terraform" Environment = "Dev" Owner = "pagoPA" - Source = "https://github.com/pagopa/pagopa-mbd-gps-service" + Source = "https://github.com/pagopa/pagopa-gps-mbd-service" CostCenter = "TS310 - PAGAMENTI & SERVIZI" } diff --git a/.identity/env/prod/backend.tfvars b/.identity/env/prod/backend.tfvars index e83b060..8b5cd7b 100644 --- a/.identity/env/prod/backend.tfvars +++ b/.identity/env/prod/backend.tfvars @@ -1,4 +1,4 @@ resource_group_name = "io-infra-rg" storage_account_name = "pagopainfraterraformprod" container_name = "azurermstate" -key = "pagopa-mbd-gps-service.tfstate" +key = "pagopa-gps-mbd-service.tfstate" diff --git a/.identity/env/prod/terraform.tfvars b/.identity/env/prod/terraform.tfvars index 60ccdcd..1c8c6e5 100644 --- a/.identity/env/prod/terraform.tfvars +++ b/.identity/env/prod/terraform.tfvars @@ -6,6 +6,6 @@ tags = { CreatedBy = "Terraform" Environment = "Prod" Owner = "pagoPA" - Source = "https://github.com/pagopa/pagopa-mbd-gps-service" + Source = "https://github.com/pagopa/pagopa-gps-mbd-service" CostCenter = "TS310 - PAGAMENTI & SERVIZI" } diff --git a/.identity/env/uat/backend.tfvars b/.identity/env/uat/backend.tfvars index 361226c..0e7cfdb 100644 --- a/.identity/env/uat/backend.tfvars +++ b/.identity/env/uat/backend.tfvars @@ -1,4 +1,4 @@ resource_group_name = "io-infra-rg" storage_account_name = "pagopainfraterraformuat" container_name = "azurermstate" -key = "pagopa-mbd-gps-service.tfstate" +key = "pagopa-gps-mbd-service.tfstate" diff --git a/.identity/env/uat/terraform.tfvars b/.identity/env/uat/terraform.tfvars index b6a3a24..7600f7f 100644 --- a/.identity/env/uat/terraform.tfvars +++ b/.identity/env/uat/terraform.tfvars @@ -6,6 +6,6 @@ tags = { CreatedBy = "Terraform" Environment = "Uat" Owner = "pagoPA" - Source = "https://github.com/pagopa/pagopa-mbd-gps-service" + Source = "https://github.com/pagopa/pagopa-gps-mbd-service" CostCenter = "TS310 - PAGAMENTI & SERVIZI" } diff --git a/README.md b/README.md index c2da3b0..e25bfde 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Expose an API that will be used by GPS Payments to generate MBD payment options -- [pagoPA MBD GPS Service](#pagopa-mbd-gps-service) +- [pagoPA MBD GPS Service](#pagopa-gps-mbd-service) * [Api Documentation 📖](#api-documentation-) * [Technology Stack](#technology-stack) * [Start Project Locally 🚀](#start-project-locally-) diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 55787b9..2b7d549 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.8' services: app: - container_name: 'pagopa-mbd-gps-service' + container_name: 'pagopa-gps-mbd-service' image: ${image} platform: linux/amd64 build: diff --git a/helm/values-dev.yaml b/helm/values-dev.yaml index 362f6e7..342f98f 100644 --- a/helm/values-dev.yaml +++ b/helm/values-dev.yaml @@ -1,9 +1,9 @@ microservice-chart: namespace: "ebollo" nameOverride: "" - fullnameOverride: "pagopa-mbd-gps-service" + fullnameOverride: "pagopa-gps-mbd-service" image: - repository: ghcr.io/pagopa/pagopa-mbd-gps-service + repository: ghcr.io/pagopa/pagopa-gps-mbd-service tag: "0.0.0" pullPolicy: Always livenessProbe: @@ -32,7 +32,7 @@ microservice-chart: ingress: create: true host: "ebollo.itn.internal.dev.platform.pagopa.it" - path: /pagopa-mbd-gps-service/(.*) + path: /pagopa-gps-mbd-service/(.*) servicePort: 8080 serviceAccount: name: "ebollo-workload-identity" @@ -68,9 +68,9 @@ microservice-chart: type: Utilization # Allowed types are 'Utilization' or 'AverageValue' value: "75" envConfig: - APP_NAME: "pagopa-mbd-gps-service" + APP_NAME: "pagopa-gps-mbd-service" APP_ENVIRONMENT: "dev" - WEBSITE_SITE_NAME: 'pagopa-mbd-gps-service' # required to show cloud role name in application insights + WEBSITE_SITE_NAME: 'pagopa-gps-mbd-service' # required to show cloud role name in application insights ENV: 'azure-dev' APP_LOGGING_LEVEL: 'INFO' DEFAULT_LOGGING_LEVEL: 'INFO' @@ -112,7 +112,7 @@ microservice-chart: deployment: create: true image: - repository: ghcr.io/pagopa/pagopa-mbd-gps-service + repository: ghcr.io/pagopa/pagopa-gps-mbd-service tag: "0.0.0" pullPolicy: Always envConfig: { } diff --git a/helm/values-prod.yaml b/helm/values-prod.yaml index 433c200..c06413c 100644 --- a/helm/values-prod.yaml +++ b/helm/values-prod.yaml @@ -1,9 +1,9 @@ microservice-chart: namespace: "ebollo" nameOverride: "" - fullnameOverride: "pagopa-mbd-gps-service" + fullnameOverride: "pagopa-gps-mbd-service" image: - repository: ghcr.io/pagopa/pagopa-mbd-gps-service + repository: ghcr.io/pagopa/pagopa-gps-mbd-service tag: "0.0.0" pullPolicy: Always livenessProbe: @@ -32,7 +32,7 @@ microservice-chart: ingress: create: true host: "ebollo.itn.internal.platform.pagopa.it" - path: /pagopa-mbd-gps-service/(.*) + path: /pagopa-gps-mbd-service/(.*) servicePort: 8080 serviceAccount: name: "ebollo-workload-identity" @@ -68,9 +68,9 @@ microservice-chart: type: Utilization # Allowed types are 'Utilization' or 'AverageValue' value: "75" envConfig: - APP_NAME: "pagopa-mbd-gps-service" + APP_NAME: "pagopa-gps-mbd-service" APP_ENVIRONMENT: "prod" - WEBSITE_SITE_NAME: 'pagopa-mbd-gps-service' # required to show cloud role name in application insights + WEBSITE_SITE_NAME: 'pagopa-gps-mbd-service' # required to show cloud role name in application insights ENV: 'azure-prod' APP_LOGGING_LEVEL: 'INFO' DEFAULT_LOGGING_LEVEL: 'INFO' @@ -104,7 +104,7 @@ microservice-chart: podAffinityTerm: labelSelector: matchLabels: - app.kubernetes.io/instance: pagopa-mbd-gps-service + app.kubernetes.io/instance: pagopa-gps-mbd-service namespaces: [ "ebollo" ] topologyKey: topology.kubernetes.io/zone canaryDelivery: @@ -121,7 +121,7 @@ microservice-chart: deployment: create: true image: - repository: ghcr.io/pagopa/pagopa-mbd-gps-service + repository: ghcr.io/pagopa/pagopa-gps-mbd-service tag: "0.0.0" pullPolicy: Always envConfig: { } diff --git a/helm/values-uat.yaml b/helm/values-uat.yaml index 894b36a..cabf580 100644 --- a/helm/values-uat.yaml +++ b/helm/values-uat.yaml @@ -1,9 +1,9 @@ microservice-chart: namespace: "ebollo" nameOverride: "" - fullnameOverride: "pagopa-mbd-gps-service" + fullnameOverride: "pagopa-gps-mbd-service" image: - repository: ghcr.io/pagopa/pagopa-mbd-gps-service + repository: ghcr.io/pagopa/pagopa-gps-mbd-service tag: "0.0.0" pullPolicy: Always livenessProbe: @@ -32,7 +32,7 @@ microservice-chart: ingress: create: true host: "ebollo.itn.internal.uat.platform.pagopa.it" - path: /pagopa-mbd-gps-service/(.*) + path: /pagopa-gps-mbd-service/(.*) servicePort: 8080 serviceAccount: name: "ebollo-workload-identity" @@ -68,9 +68,9 @@ microservice-chart: type: Utilization # Allowed types are 'Utilization' or 'AverageValue' value: "75" envConfig: - APP_NAME: "pagopa-mbd-gps-service" + APP_NAME: "pagopa-gps-mbd-service" APP_ENVIRONMENT: "uat" - WEBSITE_SITE_NAME: 'pagopa-mbd-gps-service' # required to show cloud role name in application insights + WEBSITE_SITE_NAME: 'pagopa-gps-mbd-service' # required to show cloud role name in application insights ENV: 'azure-uat' APP_LOGGING_LEVEL: 'INFO' DEFAULT_LOGGING_LEVEL: 'INFO' @@ -112,7 +112,7 @@ microservice-chart: deployment: create: true image: - repository: ghcr.io/pagopa/pagopa-mbd-gps-service + repository: ghcr.io/pagopa/pagopa-gps-mbd-service tag: "0.0.0" pullPolicy: Always envConfig: { } diff --git a/infra/04_apim_api.tf b/infra/04_apim_api.tf index 01096a9..a716b7e 100644 --- a/infra/04_apim_api.tf +++ b/infra/04_apim_api.tf @@ -3,7 +3,7 @@ locals { display_name = "MBD GPS Service" description = "API for MBD GPS Service" - path = "pagopa-mbd-gps-service" + path = "pagopa-gps-mbd-service" host = "api.${var.apim_dns_zone_prefix}.${var.external_domain}" hostname = var.hostname diff --git a/infra/policy/_base_policy.xml b/infra/policy/_base_policy.xml index 8f90c81..e812c61 100644 --- a/infra/policy/_base_policy.xml +++ b/infra/policy/_base_policy.xml @@ -1,7 +1,7 @@ - + diff --git a/openapi/openapi.json b/openapi/openapi.json index 3350f3d..1ce20d3 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -14,7 +14,7 @@ "url": "https://{host}{basePath}", "variables": { "basePath": { - "default": "/pagopa-mbd-gps-service/v1" + "default": "/pagopa-gps-mbd-service/v1" }, "host": { "default": "api.dev.platform.pagopa.it", diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/config/OpenApiConfig.java b/src/main/java/it/gov/pagopa/mbd/gps/service/config/OpenApiConfig.java index c5a65a2..3a6801e 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/config/OpenApiConfig.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/config/OpenApiConfig.java @@ -11,16 +11,14 @@ import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.security.SecurityScheme; - +import io.swagger.v3.oas.models.servers.Server; +import io.swagger.v3.oas.models.servers.ServerVariable; +import io.swagger.v3.oas.models.servers.ServerVariables; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; - -import io.swagger.v3.oas.models.servers.Server; -import io.swagger.v3.oas.models.servers.ServerVariable; -import io.swagger.v3.oas.models.servers.ServerVariables; import org.springdoc.core.customizers.GlobalOpenApiCustomizer; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -29,118 +27,122 @@ @Configuration public class OpenApiConfig { - public static final String BASE_PATH = "/pagopa-mbd-gps-service/v1"; + public static final String BASE_PATH = "/pagopa-gps-mbd-service/v1"; - @Bean - public OpenAPI customOpenAPI( - @Value("${info.application.artifactId}") String appName, - @Value("${info.application.description}") String appDescription, - @Value("${info.application.version}") String appVersion - ) { - return new OpenAPI() - .servers(List.of(new Server().url("http://localhost:8080"), - new Server().url("https://{host}{basePath}") - .variables(new ServerVariables() - .addServerVariable("host", - new ServerVariable()._enum(List.of("api.dev.platform.pagopa.it", "api.uat.platform.pagopa.it", "api.platform.pagopa.it")) - ._default("api.dev.platform.pagopa.it")) - .addServerVariable("basePath", new ServerVariable()._default(BASE_PATH)) - ))) - .components( - new Components() - .addSecuritySchemes( - "ApiKey", - new SecurityScheme() - .type(SecurityScheme.Type.APIKEY) - .description("The API key to access this function app.") - .name("Ocp-Apim-Subscription-Key") - .in(SecurityScheme.In.HEADER))) - .info( - new Info() - .title(appName) - .version(appVersion) - .description(appDescription) - .termsOfService("https://www.pagopa.gov.it/")); - } + @Bean + public OpenAPI customOpenAPI( + @Value("${info.application.artifactId}") String appName, + @Value("${info.application.description}") String appDescription, + @Value("${info.application.version}") String appVersion) { + return new OpenAPI() + .servers( + List.of( + new Server().url("http://localhost:8080"), + new Server() + .url("https://{host}{basePath}") + .variables( + new ServerVariables() + .addServerVariable( + "host", + new ServerVariable() + ._enum( + List.of( + "api.dev.platform.pagopa.it", + "api.uat.platform.pagopa.it", + "api.platform.pagopa.it")) + ._default("api.dev.platform.pagopa.it")) + .addServerVariable( + "basePath", new ServerVariable()._default(BASE_PATH))))) + .components( + new Components() + .addSecuritySchemes( + "ApiKey", + new SecurityScheme() + .type(SecurityScheme.Type.APIKEY) + .description("The API key to access this function app.") + .name("Ocp-Apim-Subscription-Key") + .in(SecurityScheme.In.HEADER))) + .info( + new Info() + .title(appName) + .version(appVersion) + .description(appDescription) + .termsOfService("https://www.pagopa.gov.it/")); + } - @Bean - public GlobalOpenApiCustomizer sortOperationsAlphabetically() { - return openApi -> { - Paths paths = - openApi - .getPaths() - .entrySet() - .stream() - .sorted(Map.Entry.comparingByKey()) - .collect( - Paths::new, - (map, item) -> map.addPathItem(item.getKey(), item.getValue()), - Paths::putAll); + @Bean + public GlobalOpenApiCustomizer sortOperationsAlphabetically() { + return openApi -> { + Paths paths = + openApi.getPaths().entrySet().stream() + .sorted(Map.Entry.comparingByKey()) + .collect( + Paths::new, + (map, item) -> map.addPathItem(item.getKey(), item.getValue()), + Paths::putAll); - paths.forEach( - (key, value) -> - value - .readOperations() - .forEach( - operation -> { - var responses = - operation - .getResponses() - .entrySet() - .stream() - .sorted(Map.Entry.comparingByKey()) - .collect( - ApiResponses::new, - (map, item) -> - map.addApiResponse(item.getKey(), item.getValue()), - ApiResponses::putAll); - operation.setResponses(responses); - })); - openApi.setPaths(paths); - }; - } + paths.forEach( + (key, value) -> + value + .readOperations() + .forEach( + operation -> { + var responses = + operation.getResponses().entrySet().stream() + .sorted(Map.Entry.comparingByKey()) + .collect( + ApiResponses::new, + (map, item) -> + map.addApiResponse(item.getKey(), item.getValue()), + ApiResponses::putAll); + operation.setResponses(responses); + })); + openApi.setPaths(paths); + }; + } - @Bean - public GlobalOpenApiCustomizer addCommonHeaders() { - return openApi -> - openApi - .getPaths() - .forEach( - (key, value) -> { + @Bean + public GlobalOpenApiCustomizer addCommonHeaders() { + return openApi -> + openApi + .getPaths() + .forEach( + (key, value) -> { - // add Request-ID as request header - var header = - Optional.ofNullable(value.getParameters()) - .orElse(Collections.emptyList()) - .parallelStream() - .filter(Objects::nonNull) - .anyMatch(elem -> HEADER_REQUEST_ID.equals(elem.getName())); - if (!header) { - value.addParametersItem( - new Parameter() - .in("header") - .name(HEADER_REQUEST_ID) - .schema(new StringSchema()) - .description( - "This header identifies the call, if not passed it is self-generated. This ID is returned in the response.")); - } + // add Request-ID as request header + var header = + Optional.ofNullable(value.getParameters()) + .orElse(Collections.emptyList()) + .parallelStream() + .filter(Objects::nonNull) + .anyMatch(elem -> HEADER_REQUEST_ID.equals(elem.getName())); + if (!header) { + value.addParametersItem( + new Parameter() + .in("header") + .name(HEADER_REQUEST_ID) + .schema(new StringSchema()) + .description( + "This header identifies the call, if not passed it is" + + " self-generated. This ID is returned in the response.")); + } - // add Request-ID as response header - value - .readOperations() - .forEach( - operation -> - operation - .getResponses() - .values() - .forEach( - response -> - response.addHeaderObject( - HEADER_REQUEST_ID, - new Header() - .schema(new StringSchema()) - .description( - "This header identifies the call")))); - }); - } + // add Request-ID as response header + value + .readOperations() + .forEach( + operation -> + operation + .getResponses() + .values() + .forEach( + response -> + response.addHeaderObject( + HEADER_REQUEST_ID, + new Header() + .schema(new StringSchema()) + .description( + "This header identifies the call")))); + }); + } } From 7f8c44ff823b4789b4641e6e3a87072d270f34d7 Mon Sep 17 00:00:00 2001 From: giomella Date: Wed, 4 Dec 2024 14:14:42 +0100 Subject: [PATCH 20/29] [PPANTT-191] add test --- .../mbd/gps/service/controller/HomeControllerTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/java/it/gov/pagopa/mbd/gps/service/controller/HomeControllerTest.java b/src/test/java/it/gov/pagopa/mbd/gps/service/controller/HomeControllerTest.java index 59ea9bb..df082a9 100644 --- a/src/test/java/it/gov/pagopa/mbd/gps/service/controller/HomeControllerTest.java +++ b/src/test/java/it/gov/pagopa/mbd/gps/service/controller/HomeControllerTest.java @@ -20,4 +20,9 @@ class HomeControllerTest { void healthCheckTestSuccess() throws Exception { mvc.perform(get("/info")).andExpect(status().isOk()); } + + @Test + void homeTestSuccess() throws Exception { + mvc.perform(get("")).andExpect(status().is3xxRedirection()); + } } \ No newline at end of file From ec3d0de61d509b141bad4458466d13a4dc14bae1 Mon Sep 17 00:00:00 2001 From: giomella Date: Wed, 4 Dec 2024 14:25:29 +0100 Subject: [PATCH 21/29] [PPANTT-191] format code with google-java-format --- .../pagopa/mbd/gps/service/Application.java | 6 +- .../mbd/gps/service/config/LoggingAspect.java | 269 ++++++++------- .../service/config/MappingsConfiguration.java | 19 +- .../mbd/gps/service/config/RequestFilter.java | 72 ++-- .../gps/service/config/ResponseValidator.java | 63 ++-- .../service/config/WebMvcConfiguration.java | 25 +- .../service/controller/HomeController.java | 78 ++--- .../service/controller/MbdGpsController.java | 93 +++-- .../mbd/gps/service/exception/AppError.java | 32 +- .../gps/service/exception/AppException.java | 128 ++++--- .../gps/service/exception/ErrorHandler.java | 321 +++++++++--------- ...tionRequestToMbdPaymentOptionResponse.java | 109 +++--- .../service/model/AppCorsConfiguration.java | 4 +- .../pagopa/mbd/gps/service/model/AppInfo.java | 6 +- .../model/MbdPaymentOptionRequest.java | 14 +- .../MbdPaymentOptionRequestProperties.java | 44 ++- .../model/MbdPaymentOptionResponse.java | 15 +- .../mbd/gps/service/model/PaymentOption.java | 79 ++--- .../mbd/gps/service/model/ProblemJson.java | 32 +- .../pagopa/mbd/gps/service/model/Stamp.java | 49 +-- .../mbd/gps/service/model/Transfer.java | 48 +-- .../mbd/gps/service/util/CommonUtility.java | 83 +++-- .../mbd/gps/service/util/Constants.java | 2 +- .../mbd/gps/service/ApplicationTest.java | 14 +- .../gps/service/OpenApiGenerationTest.java | 59 ++-- .../controller/HomeControllerTest.java | 27 +- .../controller/MbdGpsControllerTest.java | 314 ++++++++--------- 27 files changed, 1024 insertions(+), 981 deletions(-) diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/Application.java b/src/main/java/it/gov/pagopa/mbd/gps/service/Application.java index 120d1c9..5b59b26 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/Application.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/Application.java @@ -6,7 +6,7 @@ @SpringBootApplication public class Application { - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } } diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/config/LoggingAspect.java b/src/main/java/it/gov/pagopa/mbd/gps/service/config/LoggingAspect.java index 209363a..ca73f9a 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/config/LoggingAspect.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/config/LoggingAspect.java @@ -1,10 +1,15 @@ package it.gov.pagopa.mbd.gps.service.config; +import static it.gov.pagopa.mbd.gps.service.util.CommonUtility.deNull; + import it.gov.pagopa.mbd.gps.service.exception.AppError; import it.gov.pagopa.mbd.gps.service.model.ProblemJson; import jakarta.annotation.PostConstruct; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; @@ -19,148 +24,140 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import static it.gov.pagopa.mbd.gps.service.util.CommonUtility.deNull; - @Aspect @Component @Slf4j public class LoggingAspect { - public static final String START_TIME = "startTime"; - public static final String METHOD = "method"; - public static final String STATUS = "status"; - public static final String CODE = "httpCode"; - public static final String RESPONSE_TIME = "responseTime"; - public static final String FAULT_CODE = "faultCode"; - public static final String FAULT_DETAIL = "faultDetail"; - public static final String REQUEST_ID = "requestId"; - public static final String OPERATION_ID = "operationId"; - public static final String ARGS = "args"; - - HttpServletRequest httRequest; - HttpServletResponse httpResponse; - private final String name; - private final String version; - private final String environment; - - @Autowired - public LoggingAspect( - HttpServletRequest httRequest, - HttpServletResponse httpResponse, - @Value("${info.application.name}") String name, - @Value("${info.application.version}") String version, - @Value("${info.properties.environment}") String environment - ) { - this.httRequest = httRequest; - this.httpResponse = httpResponse; - this.name = name; - this.version = version; - this.environment = environment; - } - - @Pointcut("@within(org.springframework.web.bind.annotation.RestController)") - public void restController() { - // all rest controllers - } - - @Pointcut("@within(org.springframework.stereotype.Repository)") - public void repository() { - // all repository methods + public static final String START_TIME = "startTime"; + public static final String METHOD = "method"; + public static final String STATUS = "status"; + public static final String CODE = "httpCode"; + public static final String RESPONSE_TIME = "responseTime"; + public static final String FAULT_CODE = "faultCode"; + public static final String FAULT_DETAIL = "faultDetail"; + public static final String REQUEST_ID = "requestId"; + public static final String OPERATION_ID = "operationId"; + public static final String ARGS = "args"; + + HttpServletRequest httRequest; + HttpServletResponse httpResponse; + private final String name; + private final String version; + private final String environment; + + @Autowired + public LoggingAspect( + HttpServletRequest httRequest, + HttpServletResponse httpResponse, + @Value("${info.application.name}") String name, + @Value("${info.application.version}") String version, + @Value("${info.properties.environment}") String environment) { + this.httRequest = httRequest; + this.httpResponse = httpResponse; + this.name = name; + this.version = version; + this.environment = environment; + } + + @Pointcut("@within(org.springframework.web.bind.annotation.RestController)") + public void restController() { + // all rest controllers + } + + @Pointcut("@within(org.springframework.stereotype.Repository)") + public void repository() { + // all repository methods + } + + @Pointcut("@within(org.springframework.stereotype.Service)") + public void service() { + // all service methods + } + + /** Log essential info of application during the startup. */ + @PostConstruct + public void logStartup() { + log.info("-> Starting {} version {} - environment {}", name, version, environment); + } + + @Around(value = "restController()") + public Object logApiInvocation(ProceedingJoinPoint joinPoint) throws Throwable { + MDC.put(METHOD, joinPoint.getSignature().getName()); + MDC.put(START_TIME, String.valueOf(System.currentTimeMillis())); + MDC.put(OPERATION_ID, UUID.randomUUID().toString()); + if (MDC.get(REQUEST_ID) == null) { + var requestId = UUID.randomUUID().toString(); + MDC.put(REQUEST_ID, requestId); } - - @Pointcut("@within(org.springframework.stereotype.Service)") - public void service() { - // all service methods + Map params = getParams(joinPoint); + MDC.put(ARGS, params.toString()); + + log.info("Invoking API operation {} - args: {}", joinPoint.getSignature().getName(), params); + + Object result = joinPoint.proceed(); + + MDC.put(STATUS, "OK"); + MDC.put(CODE, String.valueOf(httpResponse.getStatus())); + MDC.put(RESPONSE_TIME, getExecutionTime()); + log.info( + "Successful API operation {} - result: {}", joinPoint.getSignature().getName(), result); + MDC.remove(STATUS); + MDC.remove(CODE); + MDC.remove(RESPONSE_TIME); + MDC.remove(START_TIME); + return result; + } + + @AfterReturning(value = "execution(* *..exception.ErrorHandler.*(..))", returning = "result") + public void trowingApiInvocation(JoinPoint joinPoint, ResponseEntity result) { + MDC.put(STATUS, "KO"); + MDC.put(CODE, String.valueOf(result.getStatusCodeValue())); + MDC.put(RESPONSE_TIME, getExecutionTime()); + MDC.put(FAULT_CODE, getTitle(result)); + MDC.put(FAULT_DETAIL, getDetail(result)); + log.info("Failed API operation {} - error: {}", MDC.get(METHOD), result); + MDC.clear(); + } + + @Around(value = "repository() || service()") + public Object logTrace(ProceedingJoinPoint joinPoint) throws Throwable { + Map params = getParams(joinPoint); + log.debug("Call method {} - args: {}", joinPoint.getSignature().toShortString(), params); + Object result = joinPoint.proceed(); + log.debug("Return method {} - result: {}", joinPoint.getSignature().toShortString(), result); + return result; + } + + private static String getDetail(ResponseEntity result) { + if (result != null && result.getBody() != null && result.getBody().getDetail() != null) { + return result.getBody().getDetail(); + } else return AppError.UNKNOWN.getDetails(); + } + + private static String getTitle(ResponseEntity result) { + if (result != null && result.getBody() != null && result.getBody().getTitle() != null) { + return result.getBody().getTitle(); + } else return AppError.UNKNOWN.getTitle(); + } + + public static String getExecutionTime() { + String startTime = MDC.get(START_TIME); + if (startTime != null) { + long endTime = System.currentTimeMillis(); + long executionTime = endTime - Long.parseLong(startTime); + return String.valueOf(executionTime); } - - /** - * Log essential info of application during the startup. - */ - @PostConstruct - public void logStartup() { - log.info("-> Starting {} version {} - environment {}", name, version, environment); - } - - @Around(value = "restController()") - public Object logApiInvocation(ProceedingJoinPoint joinPoint) throws Throwable { - MDC.put(METHOD, joinPoint.getSignature().getName()); - MDC.put(START_TIME, String.valueOf(System.currentTimeMillis())); - MDC.put(OPERATION_ID, UUID.randomUUID().toString()); - if (MDC.get(REQUEST_ID) == null) { - var requestId = UUID.randomUUID().toString(); - MDC.put(REQUEST_ID, requestId); - } - Map params = getParams(joinPoint); - MDC.put(ARGS, params.toString()); - - log.info("Invoking API operation {} - args: {}", joinPoint.getSignature().getName(), params); - - Object result = joinPoint.proceed(); - - MDC.put(STATUS, "OK"); - MDC.put(CODE, String.valueOf(httpResponse.getStatus())); - MDC.put(RESPONSE_TIME, getExecutionTime()); - log.info("Successful API operation {} - result: {}", joinPoint.getSignature().getName(), result); - MDC.remove(STATUS); - MDC.remove(CODE); - MDC.remove(RESPONSE_TIME); - MDC.remove(START_TIME); - return result; - } - - @AfterReturning(value = "execution(* *..exception.ErrorHandler.*(..))", returning = "result") - public void trowingApiInvocation(JoinPoint joinPoint, ResponseEntity result) { - MDC.put(STATUS, "KO"); - MDC.put(CODE, String.valueOf(result.getStatusCodeValue())); - MDC.put(RESPONSE_TIME, getExecutionTime()); - MDC.put(FAULT_CODE, getTitle(result)); - MDC.put(FAULT_DETAIL, getDetail(result)); - log.info("Failed API operation {} - error: {}", MDC.get(METHOD), result); - MDC.clear(); - } - - @Around(value = "repository() || service()") - public Object logTrace(ProceedingJoinPoint joinPoint) throws Throwable { - Map params = getParams(joinPoint); - log.debug("Call method {} - args: {}", joinPoint.getSignature().toShortString(), params); - Object result = joinPoint.proceed(); - log.debug("Return method {} - result: {}", joinPoint.getSignature().toShortString(), result); - return result; - } - - private static String getDetail(ResponseEntity result) { - if (result != null && result.getBody() != null && result.getBody().getDetail() != null) { - return result.getBody().getDetail(); - } else return AppError.UNKNOWN.getDetails(); - } - - private static String getTitle(ResponseEntity result) { - if (result != null && result.getBody() != null && result.getBody().getTitle() != null) { - return result.getBody().getTitle(); - } else return AppError.UNKNOWN.getTitle(); - } - - public static String getExecutionTime() { - String startTime = MDC.get(START_TIME); - if (startTime != null) { - long endTime = System.currentTimeMillis(); - long executionTime = endTime - Long.parseLong(startTime); - return String.valueOf(executionTime); - } - return "-"; - } - - private static Map getParams(ProceedingJoinPoint joinPoint) { - CodeSignature codeSignature = (CodeSignature) joinPoint.getSignature(); - Map params = new HashMap<>(); - int i = 0; - for (var paramName : codeSignature.getParameterNames()) { - params.put(paramName, deNull(joinPoint.getArgs()[i++])); - } - return params; + return "-"; + } + + private static Map getParams(ProceedingJoinPoint joinPoint) { + CodeSignature codeSignature = (CodeSignature) joinPoint.getSignature(); + Map params = new HashMap<>(); + int i = 0; + for (var paramName : codeSignature.getParameterNames()) { + params.put(paramName, deNull(joinPoint.getArgs()[i++])); } + return params; + } } diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/config/MappingsConfiguration.java b/src/main/java/it/gov/pagopa/mbd/gps/service/config/MappingsConfiguration.java index 76cf545..b2d0494 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/config/MappingsConfiguration.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/config/MappingsConfiguration.java @@ -11,13 +11,16 @@ @Configuration public class MappingsConfiguration { - @Bean - ModelMapper modelMapper(ConvertMbdPaymentOptionRequestToMbdPaymentOptionResponse mdbPaymentOptionResponseConverter) { - ModelMapper mapper = new ModelMapper(); - mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); + @Bean + ModelMapper modelMapper( + ConvertMbdPaymentOptionRequestToMbdPaymentOptionResponse mdbPaymentOptionResponseConverter + ) { + ModelMapper mapper = new ModelMapper(); + mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); - mapper.createTypeMap(MbdPaymentOptionRequest.class, MbdPaymentOptionResponse.class) - .setConverter(mdbPaymentOptionResponseConverter); - return mapper; - } + mapper + .createTypeMap(MbdPaymentOptionRequest.class, MbdPaymentOptionResponse.class) + .setConverter(mdbPaymentOptionResponseConverter); + return mapper; + } } diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/config/RequestFilter.java b/src/main/java/it/gov/pagopa/mbd/gps/service/config/RequestFilter.java index d18f74a..031bf11 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/config/RequestFilter.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/config/RequestFilter.java @@ -1,5 +1,7 @@ package it.gov.pagopa.mbd.gps.service.config; +import static it.gov.pagopa.mbd.gps.service.util.Constants.HEADER_REQUEST_ID; + import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; @@ -7,53 +9,49 @@ import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.UUID; import lombok.extern.slf4j.Slf4j; import org.slf4j.MDC; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; -import java.io.IOException; -import java.util.UUID; - -import static it.gov.pagopa.mbd.gps.service.util.Constants.HEADER_REQUEST_ID; - @Component @Order(Ordered.HIGHEST_PRECEDENCE) @Slf4j public class RequestFilter implements Filter { - /** - * Get the request ID from the custom header "X-Request-Id" if present, otherwise it generates - * one. Set the X-Request-Id value in the {@code response} and in the MDC - * - * @param request http request - * @param response http response - * @param chain next filter - * @throws IOException if an I/O error occurs during this filter's processing of the request - * @throws ServletException if the processing fails for any other reason - */ - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { - try { - HttpServletRequest httRequest = (HttpServletRequest) request; - - // get requestId from header or generate one - String requestId = httRequest.getHeader(HEADER_REQUEST_ID); - if (requestId == null || requestId.isEmpty()) { - requestId = UUID.randomUUID().toString(); - } - - // set requestId in MDC - MDC.put("requestId", requestId); - - // set requestId in the response header - ((HttpServletResponse) response).setHeader(HEADER_REQUEST_ID, requestId); - chain.doFilter(request, response); - } finally { - MDC.clear(); - } + /** + * Get the request ID from the custom header "X-Request-Id" if present, otherwise it generates + * one. Set the X-Request-Id value in the {@code response} and in the MDC + * + * @param request http request + * @param response http response + * @param chain next filter + * @throws IOException if an I/O error occurs during this filter's processing of the request + * @throws ServletException if the processing fails for any other reason + */ + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + try { + HttpServletRequest httRequest = (HttpServletRequest) request; + + // get requestId from header or generate one + String requestId = httRequest.getHeader(HEADER_REQUEST_ID); + if (requestId == null || requestId.isEmpty()) { + requestId = UUID.randomUUID().toString(); + } + + // set requestId in MDC + MDC.put("requestId", requestId); + + // set requestId in the response header + ((HttpServletResponse) response).setHeader(HEADER_REQUEST_ID, requestId); + chain.doFilter(request, response); + } finally { + MDC.clear(); } - + } } diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/config/ResponseValidator.java b/src/main/java/it/gov/pagopa/mbd/gps/service/config/ResponseValidator.java index 2a0713b..c7ca490 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/config/ResponseValidator.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/config/ResponseValidator.java @@ -3,6 +3,7 @@ import it.gov.pagopa.mbd.gps.service.exception.AppException; import jakarta.validation.ConstraintViolation; import jakarta.validation.Validator; +import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; @@ -12,44 +13,44 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; -import java.util.Set; - @Aspect @Component public class ResponseValidator { - private final Validator validator; - - @Autowired - public ResponseValidator(Validator validator) { - this.validator = validator; - } - - /** - * This method validates the response annotated with the {@link jakarta.validation.constraints} - * - * @param joinPoint not used - * @param result the response to validate - */ - @AfterReturning(pointcut = "execution(* it.gov.pagopa.mbd.gps.service.controller.*.*(..))", returning = "result") - public void validateResponse(JoinPoint joinPoint, Object result) { - if (result instanceof ResponseEntity) { - validateResponse((ResponseEntity) result); - } + private final Validator validator; + + @Autowired + public ResponseValidator(Validator validator) { + this.validator = validator; + } + + /** + * This method validates the response annotated with the {@link jakarta.validation.constraints} + * + * @param joinPoint not used + * @param result the response to validate + */ + @AfterReturning( + pointcut = "execution(* it.gov.pagopa.mbd.gps.service.controller.*.*(..))", + returning = "result") + public void validateResponse(JoinPoint joinPoint, Object result) { + if (result instanceof ResponseEntity) { + validateResponse((ResponseEntity) result); } + } - private void validateResponse(ResponseEntity response) { - if (response.getBody() != null) { - Set> validationResults = validator.validate(response.getBody()); + private void validateResponse(ResponseEntity response) { + if (response.getBody() != null) { + Set> validationResults = validator.validate(response.getBody()); - if (!validationResults.isEmpty()) { - var sb = new StringBuilder(); - for (ConstraintViolation error : validationResults) { - sb.append(error.getPropertyPath()).append(" ").append(error.getMessage()).append(". "); - } - var msg = StringUtils.chop(sb.toString()); - throw new AppException(HttpStatus.INTERNAL_SERVER_ERROR, "Invalid response", msg); - } + if (!validationResults.isEmpty()) { + var sb = new StringBuilder(); + for (ConstraintViolation error : validationResults) { + sb.append(error.getPropertyPath()).append(" ").append(error.getMessage()).append(". "); } + var msg = StringUtils.chop(sb.toString()); + throw new AppException(HttpStatus.INTERNAL_SERVER_ERROR, "Invalid response", msg); + } } + } } diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/config/WebMvcConfiguration.java b/src/main/java/it/gov/pagopa/mbd/gps/service/config/WebMvcConfiguration.java index 2cbbfc3..8f43fda 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/config/WebMvcConfiguration.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/config/WebMvcConfiguration.java @@ -11,18 +11,17 @@ @Configuration public class WebMvcConfiguration implements WebMvcConfigurer { - @Value("${cors.configuration}") - private String corsConfiguration; + @Value("${cors.configuration}") + private String corsConfiguration; - @SneakyThrows - @Override - public void addCorsMappings(CorsRegistry registry) { - AppCorsConfiguration appCorsConfiguration = new ObjectMapper().readValue(corsConfiguration, - AppCorsConfiguration.class); - registry.addMapping("/**") - .allowedOrigins(appCorsConfiguration.getOrigins()) - .allowedMethods(appCorsConfiguration.getMethods()); - } + @SneakyThrows + @Override + public void addCorsMappings(CorsRegistry registry) { + AppCorsConfiguration appCorsConfiguration = + new ObjectMapper().readValue(corsConfiguration, AppCorsConfiguration.class); + registry + .addMapping("/**") + .allowedOrigins(appCorsConfiguration.getOrigins()) + .allowedMethods(appCorsConfiguration.getMethods()); + } } - - diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/controller/HomeController.java b/src/main/java/it/gov/pagopa/mbd/gps/service/controller/HomeController.java index d53971a..d858b41 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/controller/HomeController.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/controller/HomeController.java @@ -17,44 +17,44 @@ @Validated public class HomeController { - @Value("${server.servlet.context-path}") - String basePath; - - @Value("${info.application.name}") - private String name; - - @Value("${info.application.version}") - private String version; - - @Value("${info.properties.environment}") - private String environment; - - /** - * @return redirect to Swagger page documentation - */ - @Hidden - @GetMapping("") - public RedirectView home() { - if (!basePath.endsWith("/")) { - basePath += "/"; - } - return new RedirectView(basePath + "swagger-ui.html"); - } - - /** - * Return app name, version and environment - * - * @return the app info - */ - @Operation( - summary = "health check", - description = "Return OK if application is started", - security = {@SecurityRequirement(name = "ApiKey")}, - tags = {"Home"}) - @GetMapping(value = "/info") - @ResponseStatus(HttpStatus.OK) - public ResponseEntity healthCheck() { - AppInfo info = AppInfo.builder().name(name).version(version).environment(environment).build(); - return ResponseEntity.status(HttpStatus.OK).body(info); + @Value("${server.servlet.context-path}") + String basePath; + + @Value("${info.application.name}") + private String name; + + @Value("${info.application.version}") + private String version; + + @Value("${info.properties.environment}") + private String environment; + + /** + * @return redirect to Swagger page documentation + */ + @Hidden + @GetMapping("") + public RedirectView home() { + if (!basePath.endsWith("/")) { + basePath += "/"; } + return new RedirectView(basePath + "swagger-ui.html"); + } + + /** + * Return app name, version and environment + * + * @return the app info + */ + @Operation( + summary = "health check", + description = "Return OK if application is started", + security = {@SecurityRequirement(name = "ApiKey")}, + tags = {"Home"}) + @GetMapping(value = "/info") + @ResponseStatus(HttpStatus.OK) + public ResponseEntity healthCheck() { + AppInfo info = AppInfo.builder().name(name).version(version).environment(environment).build(); + return ResponseEntity.status(HttpStatus.OK).body(info); + } } diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsController.java b/src/main/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsController.java index 47bf223..c72bb1e 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsController.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsController.java @@ -23,41 +23,68 @@ import org.springframework.web.bind.annotation.RestController; @RestController -@RequestMapping(consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) +@RequestMapping( + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) @Tag(name = "MBD GPS") public class MbdGpsController { - private final ModelMapper modelMapper; + private final ModelMapper modelMapper; - @Autowired - public MbdGpsController(ModelMapper modelMapper) { - this.modelMapper = modelMapper; - } + @Autowired + public MbdGpsController(ModelMapper modelMapper) { + this.modelMapper = modelMapper; + } - /** - * Map MBD service specific data into payment option model - * - * @param mbdPaymentOptionRequest MBD data - * @return the mapped model - */ - @PostMapping("/mbd/paymentOption") - @ResponseStatus(HttpStatus.CREATED) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, - schema = @Schema(implementation = MbdPaymentOptionResponse.class))), - @ApiResponse(responseCode = "400", description = "Bad Request", - content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ProblemJson.class))), - @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(schema = @Schema())), - @ApiResponse(responseCode = "404", description = "Not found", content = @Content(schema = @Schema(implementation = ProblemJson.class))), - @ApiResponse(responseCode = "429", description = "Too many requests", content = @Content(schema = @Schema())), - @ApiResponse(responseCode = "500", description = "Service unavailable", - content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ProblemJson.class))) - }) - @Operation(summary = "Create MBD payment option", security = {@SecurityRequirement(name = "ApiKey")}) - public @Valid MbdPaymentOptionResponse createMdbPaymentOption( - @RequestBody @NotNull @Valid MbdPaymentOptionRequest mbdPaymentOptionRequest - ) { - return this.modelMapper.map(mbdPaymentOptionRequest, MbdPaymentOptionResponse.class); - } -} \ No newline at end of file + /** + * Map MBD service specific data into payment option model + * + * @param mbdPaymentOptionRequest MBD data + * @return the mapped model + */ + @PostMapping("/mbd/paymentOption") + @ResponseStatus(HttpStatus.CREATED) + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "OK", + content = + @Content( + mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = MbdPaymentOptionResponse.class))), + @ApiResponse( + responseCode = "400", + description = "Bad Request", + content = + @Content( + mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = ProblemJson.class))), + @ApiResponse( + responseCode = "401", + description = "Unauthorized", + content = @Content(schema = @Schema())), + @ApiResponse( + responseCode = "404", + description = "Not found", + content = @Content(schema = @Schema(implementation = ProblemJson.class))), + @ApiResponse( + responseCode = "429", + description = "Too many requests", + content = @Content(schema = @Schema())), + @ApiResponse( + responseCode = "500", + description = "Service unavailable", + content = + @Content( + mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = ProblemJson.class))) + }) + @Operation( + summary = "Create MBD payment option", + security = {@SecurityRequirement(name = "ApiKey")}) + public @Valid MbdPaymentOptionResponse createMdbPaymentOption( + @RequestBody @NotNull @Valid MbdPaymentOptionRequest mbdPaymentOptionRequest) { + return this.modelMapper.map(mbdPaymentOptionRequest, MbdPaymentOptionResponse.class); + } +} diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/exception/AppError.java b/src/main/java/it/gov/pagopa/mbd/gps/service/exception/AppError.java index e1226ad..1f73112 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/exception/AppError.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/exception/AppError.java @@ -5,23 +5,23 @@ @Getter public enum AppError { - INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "Internal Server Error", "Something was wrong"), - BAD_REQUEST(HttpStatus.INTERNAL_SERVER_ERROR, "Bad Request", "%s"), - UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "Unauthorized", "Error during authentication"), - FORBIDDEN(HttpStatus.FORBIDDEN, "Forbidden", "This method is forbidden"), - RESPONSE_NOT_READABLE(HttpStatus.BAD_GATEWAY, "Response Not Readable", "The response body is not readable"), + INTERNAL_SERVER_ERROR( + HttpStatus.INTERNAL_SERVER_ERROR, "Internal Server Error", "Something was wrong"), + BAD_REQUEST(HttpStatus.INTERNAL_SERVER_ERROR, "Bad Request", "%s"), + UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "Unauthorized", "Error during authentication"), + FORBIDDEN(HttpStatus.FORBIDDEN, "Forbidden", "This method is forbidden"), + RESPONSE_NOT_READABLE( + HttpStatus.BAD_GATEWAY, "Response Not Readable", "The response body is not readable"), - UNKNOWN(null, null, null); + UNKNOWN(null, null, null); - public final HttpStatus httpStatus; - public final String title; - public final String details; + public final HttpStatus httpStatus; + public final String title; + public final String details; - AppError(HttpStatus httpStatus, String title, String details) { - this.httpStatus = httpStatus; - this.title = title; - this.details = details; - } + AppError(HttpStatus httpStatus, String title, String details) { + this.httpStatus = httpStatus; + this.title = title; + this.details = details; + } } - - diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/exception/AppException.java b/src/main/java/it/gov/pagopa/mbd/gps/service/exception/AppException.java index 91fdbe3..15e0273 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/exception/AppException.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/exception/AppException.java @@ -1,90 +1,86 @@ package it.gov.pagopa.mbd.gps.service.exception; import jakarta.validation.constraints.NotNull; +import java.util.Formatter; import lombok.EqualsAndHashCode; import lombok.Value; import org.springframework.http.HttpStatus; import org.springframework.validation.annotation.Validated; -import java.util.Formatter; - /** * Custom exception. - *

See {@link ErrorHandler} + * + *

See {@link ErrorHandler} */ @EqualsAndHashCode(callSuper = true) @Value @Validated public class AppException extends RuntimeException { - /** - * title returned to the response when this exception occurred - */ - String title; - - /** - * http status returned to the response when this exception occurred - */ - HttpStatus httpStatus; + /** title returned to the response when this exception occurred */ + String title; - /** - * @param httpStatus HTTP status returned to the response - * @param title title returned to the response when this exception occurred - * @param message the detail message returend to the response - * @param cause The cause of this {@link AppException} - */ - public AppException( - @NotNull HttpStatus httpStatus, @NotNull String title, - @NotNull String message, Throwable cause - ) { - super(message, cause); - this.title = title; - this.httpStatus = httpStatus; - } + /** http status returned to the response when this exception occurred */ + HttpStatus httpStatus; - /** - * @param httpStatus HTTP status returned to the response - * @param title title returned to the response when this exception occurred - * @param message the detail message returend to the response - */ - public AppException(@NotNull HttpStatus httpStatus, @NotNull String title, @NotNull String message) { - super(message); - this.title = title; - this.httpStatus = httpStatus; - } + /** + * @param httpStatus HTTP status returned to the response + * @param title title returned to the response when this exception occurred + * @param message the detail message returend to the response + * @param cause The cause of this {@link AppException} + */ + public AppException( + @NotNull HttpStatus httpStatus, + @NotNull String title, + @NotNull String message, + Throwable cause) { + super(message, cause); + this.title = title; + this.httpStatus = httpStatus; + } + /** + * @param httpStatus HTTP status returned to the response + * @param title title returned to the response when this exception occurred + * @param message the detail message returend to the response + */ + public AppException( + @NotNull HttpStatus httpStatus, @NotNull String title, @NotNull String message) { + super(message); + this.title = title; + this.httpStatus = httpStatus; + } - /** - * @param appError Response template returned to the response - * @param args {@link Formatter} replaces the placeholders in "details" string of - * {@link AppError} with the arguments. If there are more arguments than format - * specifiers, the extra arguments are ignored. - */ - public AppException(@NotNull AppError appError, Object... args) { - super(formatDetails(appError, args)); - this.httpStatus = appError.httpStatus; - this.title = appError.title; - } + /** + * @param appError Response template returned to the response + * @param args {@link Formatter} replaces the placeholders in "details" string of {@link AppError} + * with the arguments. If there are more arguments than format specifiers, the extra arguments + * are ignored. + */ + public AppException(@NotNull AppError appError, Object... args) { + super(formatDetails(appError, args)); + this.httpStatus = appError.httpStatus; + this.title = appError.title; + } - /** - * @param appError Response template returned to the response - * @param cause The cause of this {@link AppException} - * @param args Arguments for the details of {@link AppError} replaced by the - * {@link Formatter}. If there are more arguments than format specifiers, the - * extra arguments are ignored. - */ - public AppException(@NotNull AppError appError, Throwable cause, Object... args) { - super(formatDetails(appError, args), cause); - this.httpStatus = appError.httpStatus; - this.title = appError.title; - } + /** + * @param appError Response template returned to the response + * @param cause The cause of this {@link AppException} + * @param args Arguments for the details of {@link AppError} replaced by the {@link Formatter}. If + * there are more arguments than format specifiers, the extra arguments are ignored. + */ + public AppException(@NotNull AppError appError, Throwable cause, Object... args) { + super(formatDetails(appError, args), cause); + this.httpStatus = appError.httpStatus; + this.title = appError.title; + } - private static String formatDetails(AppError appError, Object[] args) { - return String.format(appError.details, args); - } + private static String formatDetails(AppError appError, Object[] args) { + return String.format(appError.details, args); + } - @Override - public String toString() { - return "AppException(" + httpStatus + ", " + title + ")" + super.toString(); - } + @Override + public String toString() { + return "AppException(" + httpStatus + ", " + title + ")" + super.toString(); + } } diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/exception/ErrorHandler.java b/src/main/java/it/gov/pagopa/mbd/gps/service/exception/ErrorHandler.java index 2889a81..314d025 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/exception/ErrorHandler.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/exception/ErrorHandler.java @@ -2,6 +2,8 @@ import it.gov.pagopa.mbd.gps.service.model.ProblemJson; import jakarta.validation.ConstraintViolationException; +import java.util.ArrayList; +import java.util.List; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.TypeMismatchException; import org.springframework.http.HttpHeaders; @@ -18,180 +20,171 @@ import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; -import java.util.ArrayList; -import java.util.List; - -/** - * All Exceptions are handled by this class - */ +/** All Exceptions are handled by this class */ @ControllerAdvice @Slf4j public class ErrorHandler extends ResponseEntityExceptionHandler { - /** - * Handle if the input request is not a valid JSON - * - * @param ex {@link HttpMessageNotReadableException} exception raised - * @param headers of the response - * @param status of the response - * @param request from frontend - * @return a {@link ProblemJson} as response with the cause and with a 400 as HTTP status - */ - @Override - public ResponseEntity handleHttpMessageNotReadable( - HttpMessageNotReadableException ex, - HttpHeaders headers, - HttpStatusCode status, - WebRequest request - ) { - log.warn("Input not readable: ", ex); - var errorResponse = ProblemJson.builder() - .status(HttpStatus.BAD_REQUEST.value()) - .title(AppError.BAD_REQUEST.getTitle()) - .detail("Invalid input format") - .build(); - return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); - } + /** + * Handle if the input request is not a valid JSON + * + * @param ex {@link HttpMessageNotReadableException} exception raised + * @param headers of the response + * @param status of the response + * @param request from frontend + * @return a {@link ProblemJson} as response with the cause and with a 400 as HTTP status + */ + @Override + public ResponseEntity handleHttpMessageNotReadable( + HttpMessageNotReadableException ex, + HttpHeaders headers, + HttpStatusCode status, + WebRequest request) { + log.warn("Input not readable: ", ex); + var errorResponse = + ProblemJson.builder() + .status(HttpStatus.BAD_REQUEST.value()) + .title(AppError.BAD_REQUEST.getTitle()) + .detail("Invalid input format") + .build(); + return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); + } - /** - * Handle if missing some request parameters in the request - * - * @param ex {@link MissingServletRequestParameterException} exception raised - * @param headers of the response - * @param status of the response - * @param request from frontend - * @return a {@link ProblemJson} as response with the cause and with a 400 as HTTP status - */ - @Override - public ResponseEntity handleMissingServletRequestParameter( - MissingServletRequestParameterException ex, - HttpHeaders headers, - HttpStatusCode status, - WebRequest request - ) { - log.warn("Missing request parameter: ", ex); - var errorResponse = ProblemJson.builder() - .status(HttpStatus.BAD_REQUEST.value()) - .title(AppError.BAD_REQUEST.getTitle()) - .detail(ex.getMessage()) - .build(); - return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); - } + /** + * Handle if missing some request parameters in the request + * + * @param ex {@link MissingServletRequestParameterException} exception raised + * @param headers of the response + * @param status of the response + * @param request from frontend + * @return a {@link ProblemJson} as response with the cause and with a 400 as HTTP status + */ + @Override + public ResponseEntity handleMissingServletRequestParameter( + MissingServletRequestParameterException ex, + HttpHeaders headers, + HttpStatusCode status, + WebRequest request) { + log.warn("Missing request parameter: ", ex); + var errorResponse = + ProblemJson.builder() + .status(HttpStatus.BAD_REQUEST.value()) + .title(AppError.BAD_REQUEST.getTitle()) + .detail(ex.getMessage()) + .build(); + return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); + } + /** + * Customize the response for TypeMismatchException. + * + * @param ex the exception + * @param headers the headers to be written to the response + * @param status the selected response status + * @param request the current request + * @return a {@code ResponseEntity} instance + */ + @Override + protected ResponseEntity handleTypeMismatch( + TypeMismatchException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { + log.warn("Type mismatch: ", ex); + var errorResponse = + ProblemJson.builder() + .status(HttpStatus.BAD_REQUEST.value()) + .title(AppError.BAD_REQUEST.getTitle()) + .detail( + String.format( + "Invalid value %s for property %s", + ex.getValue(), ((MethodArgumentTypeMismatchException) ex).getName())) + .build(); + return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); + } - /** - * Customize the response for TypeMismatchException. - * - * @param ex the exception - * @param headers the headers to be written to the response - * @param status the selected response status - * @param request the current request - * @return a {@code ResponseEntity} instance - */ - @Override - protected ResponseEntity handleTypeMismatch( - TypeMismatchException ex, - HttpHeaders headers, - HttpStatusCode status, - WebRequest request - ) { - log.warn("Type mismatch: ", ex); - var errorResponse = ProblemJson.builder() - .status(HttpStatus.BAD_REQUEST.value()) - .title(AppError.BAD_REQUEST.getTitle()) - .detail(String.format("Invalid value %s for property %s", ex.getValue(), - ((MethodArgumentTypeMismatchException) ex).getName())) - .build(); - return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); + /** + * Handle if validation constraints are unsatisfied + * + * @param ex {@link MethodArgumentNotValidException} exception raised + * @param headers of the response + * @param status of the response + * @param request from frontend + * @return a {@link ProblemJson} as response with the cause and with a 400 as HTTP status + */ + @Override + protected ResponseEntity handleMethodArgumentNotValid( + MethodArgumentNotValidException ex, + HttpHeaders headers, + HttpStatusCode status, + WebRequest request) { + List details = new ArrayList<>(); + for (FieldError error : ex.getBindingResult().getFieldErrors()) { + details.add(error.getField() + ": " + error.getDefaultMessage()); } + var detailsMessage = String.join(", ", details); + log.warn("Input not valid: " + detailsMessage); + var errorResponse = + ProblemJson.builder() + .status(HttpStatus.BAD_REQUEST.value()) + .title(AppError.BAD_REQUEST.getTitle()) + .detail(detailsMessage) + .build(); + return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); + } - /** - * Handle if validation constraints are unsatisfied - * - * @param ex {@link MethodArgumentNotValidException} exception raised - * @param headers of the response - * @param status of the response - * @param request from frontend - * @return a {@link ProblemJson} as response with the cause and with a 400 as HTTP status - */ - @Override - protected ResponseEntity handleMethodArgumentNotValid( - MethodArgumentNotValidException ex, - HttpHeaders headers, - HttpStatusCode status, - WebRequest request - ) { - List details = new ArrayList<>(); - for (FieldError error : ex.getBindingResult().getFieldErrors()) { - details.add(error.getField() + ": " + error.getDefaultMessage()); - } - var detailsMessage = String.join(", ", details); - log.warn("Input not valid: " + detailsMessage); - var errorResponse = ProblemJson.builder() - .status(HttpStatus.BAD_REQUEST.value()) - .title(AppError.BAD_REQUEST.getTitle()) - .detail(detailsMessage) - .build(); - return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); - } + @ExceptionHandler({ConstraintViolationException.class}) + public ResponseEntity handleConstraintViolationException( + final ConstraintViolationException ex, final WebRequest request) { + log.warn("Validation Error raised:", ex); + var errorResponse = + ProblemJson.builder() + .status(HttpStatus.BAD_REQUEST.value()) + .title(AppError.BAD_REQUEST.getTitle()) + .detail(ex.getMessage()) + .build(); + return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); + } - @ExceptionHandler({ConstraintViolationException.class}) - public ResponseEntity handleConstraintViolationException( - final ConstraintViolationException ex, - final WebRequest request - ) { - log.warn("Validation Error raised:", ex); - var errorResponse = ProblemJson.builder() - .status(HttpStatus.BAD_REQUEST.value()) - .title(AppError.BAD_REQUEST.getTitle()) - .detail(ex.getMessage()) - .build(); - return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); + /** + * Handle if a {@link AppException} is raised + * + * @param ex {@link AppException} exception raised + * @param request from frontend + * @return a {@link ProblemJson} as response with the cause and with an appropriated HTTP status + */ + @ExceptionHandler({AppException.class}) + public ResponseEntity handleAppException( + final AppException ex, final WebRequest request) { + if (ex.getCause() != null) { + log.warn( + "App Exception raised: {}\nCause of the App Exception: ", ex.getMessage(), ex.getCause()); + } else { + log.warn("App Exception raised: ", ex); } + var errorResponse = + ProblemJson.builder() + .status(ex.getHttpStatus().value()) + .title(ex.getTitle()) + .detail(ex.getMessage()) + .build(); + return new ResponseEntity<>(errorResponse, ex.getHttpStatus()); + } - /** - * Handle if a {@link AppException} is raised - * - * @param ex {@link AppException} exception raised - * @param request from frontend - * @return a {@link ProblemJson} as response with the cause and with an appropriated HTTP status - */ - @ExceptionHandler({AppException.class}) - public ResponseEntity handleAppException( - final AppException ex, - final WebRequest request - ) { - if (ex.getCause() != null) { - log.warn("App Exception raised: {}\nCause of the App Exception: ", ex.getMessage(), ex.getCause()); - } else { - log.warn("App Exception raised: ", ex); - } - var errorResponse = ProblemJson.builder() - .status(ex.getHttpStatus().value()) - .title(ex.getTitle()) - .detail(ex.getMessage()) - .build(); - return new ResponseEntity<>(errorResponse, ex.getHttpStatus()); - } - - /** - * Handle if a {@link Exception} is raised - * - * @param ex {@link Exception} exception raised - * @param request from frontend - * @return a {@link ProblemJson} as response with the cause and with 500 as HTTP status - */ - @ExceptionHandler({Exception.class}) - public ResponseEntity handleGenericException( - final Exception ex, - final WebRequest request - ) { - log.error("Generic Exception raised:", ex); - var errorResponse = ProblemJson.builder() - .status(HttpStatus.INTERNAL_SERVER_ERROR.value()) - .title(AppError.INTERNAL_SERVER_ERROR.getTitle()) - .detail(ex.getMessage()) - .build(); - return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR); - } + /** + * Handle if a {@link Exception} is raised + * + * @param ex {@link Exception} exception raised + * @param request from frontend + * @return a {@link ProblemJson} as response with the cause and with 500 as HTTP status + */ + @ExceptionHandler({Exception.class}) + public ResponseEntity handleGenericException( + final Exception ex, final WebRequest request) { + log.error("Generic Exception raised:", ex); + var errorResponse = + ProblemJson.builder() + .status(HttpStatus.INTERNAL_SERVER_ERROR.value()) + .title(AppError.INTERNAL_SERVER_ERROR.getTitle()) + .detail(ex.getMessage()) + .build(); + return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR); + } } diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/mapper/ConvertMbdPaymentOptionRequestToMbdPaymentOptionResponse.java b/src/main/java/it/gov/pagopa/mbd/gps/service/mapper/ConvertMbdPaymentOptionRequestToMbdPaymentOptionResponse.java index 216ae3a..f015718 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/mapper/ConvertMbdPaymentOptionRequestToMbdPaymentOptionResponse.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/mapper/ConvertMbdPaymentOptionRequestToMbdPaymentOptionResponse.java @@ -1,77 +1,82 @@ package it.gov.pagopa.mbd.gps.service.mapper; -import it.gov.pagopa.mbd.gps.service.model.MbdPaymentOptionRequestProperties; -import it.gov.pagopa.mbd.gps.service.model.PaymentOption; import it.gov.pagopa.mbd.gps.service.model.MbdPaymentOptionRequest; +import it.gov.pagopa.mbd.gps.service.model.MbdPaymentOptionRequestProperties; import it.gov.pagopa.mbd.gps.service.model.MbdPaymentOptionResponse; +import it.gov.pagopa.mbd.gps.service.model.PaymentOption; import it.gov.pagopa.mbd.gps.service.model.Stamp; import it.gov.pagopa.mbd.gps.service.model.Transfer; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.Collections; import org.modelmapper.Converter; import org.modelmapper.spi.MappingContext; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import java.time.LocalDateTime; -import java.time.temporal.ChronoUnit; -import java.util.Collections; - /** - * Converter class that specify how to convert a {@link MbdPaymentOptionRequest} instance to a {@link MbdPaymentOptionResponse} instance + * Converter class that specify how to convert a {@link MbdPaymentOptionRequest} instance to a + * {@link MbdPaymentOptionResponse} instance */ @Component -public class ConvertMbdPaymentOptionRequestToMbdPaymentOptionResponse implements Converter { +public class ConvertMbdPaymentOptionRequestToMbdPaymentOptionResponse + implements Converter { - private static final boolean IS_PARTIAL_PAYMENT = false; - private static final String ID_TRANSFER = "1"; - private static final String STAMP_TYPE = "st"; + private static final boolean IS_PARTIAL_PAYMENT = false; + private static final String ID_TRANSFER = "1"; + private static final String STAMP_TYPE = "st"; - @Value("${mbd.payment-option.description}") - private String description; + @Value("${mbd.payment-option.description}") + private String description; - @Value("${mbd.transfer.remittance-information}") - private String remittanceInformation; + @Value("${mbd.transfer.remittance-information}") + private String remittanceInformation; - @Value("${mbd.payment-option.due-date-delta}") - private int dueDateDelta; + @Value("${mbd.payment-option.due-date-delta}") + private int dueDateDelta; - @Value("${mbd.payment-option.due-date-delta-time-unit}") - private ChronoUnit dueDateDeltaTimeUnit; + @Value("${mbd.payment-option.due-date-delta-time-unit}") + private ChronoUnit dueDateDeltaTimeUnit; - @Value("${mbd.payment-option.retention-date-delta}") - private int retentionDateDelta; + @Value("${mbd.payment-option.retention-date-delta}") + private int retentionDateDelta; - @Value("${mbd.payment-option.retention-date-delta-time-unit}") - private ChronoUnit retentionDateDeltaTimeUnit; + @Value("${mbd.payment-option.retention-date-delta-time-unit}") + private ChronoUnit retentionDateDeltaTimeUnit; - @Override - public MbdPaymentOptionResponse convert(MappingContext context) { - MbdPaymentOptionRequestProperties model = context.getSource().getProperties(); + @Override + public MbdPaymentOptionResponse convert( + MappingContext context) { + MbdPaymentOptionRequestProperties model = context.getSource().getProperties(); - Transfer transfer = Transfer.builder() - .amount(model.getAmount()) - .idTransfer(ID_TRANSFER) - .organizationFiscalCode(model.getFiscalCode()) - .remittanceInformation(remittanceInformation) - .stamp(Stamp.builder() - .hashDocument(model.getDocumentHash()) - .provincialResidence(model.getProvincialResidence()) - .stampType(STAMP_TYPE) - .build()) - .build(); + Transfer transfer = + Transfer.builder() + .amount(model.getAmount()) + .idTransfer(ID_TRANSFER) + .organizationFiscalCode(model.getFiscalCode()) + .remittanceInformation(remittanceInformation) + .stamp( + Stamp.builder() + .hashDocument(model.getDocumentHash()) + .provincialResidence(model.getProvincialResidence()) + .stampType(STAMP_TYPE) + .build()) + .build(); - PaymentOption paymentOption = PaymentOption.builder() - .firstName(model.getFirstName()) - .lastName(model.getLastName()) - .amount(model.getAmount()) - .description(description) - .dueDate(LocalDateTime.now().plus(dueDateDelta, dueDateDeltaTimeUnit)) - .retentionDate(LocalDateTime.now().plus(retentionDateDelta, retentionDateDeltaTimeUnit)) - .isPartialPayment(IS_PARTIAL_PAYMENT) - .transfer(Collections.singletonList(transfer)) - .build(); + PaymentOption paymentOption = + PaymentOption.builder() + .firstName(model.getFirstName()) + .lastName(model.getLastName()) + .amount(model.getAmount()) + .description(description) + .dueDate(LocalDateTime.now().plus(dueDateDelta, dueDateDeltaTimeUnit)) + .retentionDate(LocalDateTime.now().plus(retentionDateDelta, retentionDateDeltaTimeUnit)) + .isPartialPayment(IS_PARTIAL_PAYMENT) + .transfer(Collections.singletonList(transfer)) + .build(); - return MbdPaymentOptionResponse.builder() - .paymentOption(Collections.singletonList(paymentOption)) - .build(); - } -} \ No newline at end of file + return MbdPaymentOptionResponse.builder() + .paymentOption(Collections.singletonList(paymentOption)) + .build(); + } +} diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/model/AppCorsConfiguration.java b/src/main/java/it/gov/pagopa/mbd/gps/service/model/AppCorsConfiguration.java index 1d77e54..0a228c5 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/model/AppCorsConfiguration.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/model/AppCorsConfiguration.java @@ -18,6 +18,6 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class AppCorsConfiguration { - private String[] origins; - private String[] methods; + private String[] origins; + private String[] methods; } diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/model/AppInfo.java b/src/main/java/it/gov/pagopa/mbd/gps/service/model/AppInfo.java index 3334458..d0665f8 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/model/AppInfo.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/model/AppInfo.java @@ -16,7 +16,7 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class AppInfo { - private String name; - private String version; - private String environment; + private String name; + private String version; + private String environment; } diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/model/MbdPaymentOptionRequest.java b/src/main/java/it/gov/pagopa/mbd/gps/service/model/MbdPaymentOptionRequest.java index 6318532..88f3c0c 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/model/MbdPaymentOptionRequest.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/model/MbdPaymentOptionRequest.java @@ -7,16 +7,16 @@ import lombok.Data; import lombok.NoArgsConstructor; -/** - * Model class that holds MBD GPS request - */ +/** Model class that holds MBD GPS request */ @Data @Builder @AllArgsConstructor @NoArgsConstructor public class MbdPaymentOptionRequest { - @Valid - @Schema(description = "MBD payment option's properties", requiredMode = Schema.RequiredMode.REQUIRED) - private MbdPaymentOptionRequestProperties properties; -} \ No newline at end of file + @Valid + @Schema( + description = "MBD payment option's properties", + requiredMode = Schema.RequiredMode.REQUIRED) + private MbdPaymentOptionRequestProperties properties; +} diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/model/MbdPaymentOptionRequestProperties.java b/src/main/java/it/gov/pagopa/mbd/gps/service/model/MbdPaymentOptionRequestProperties.java index 42e1b9c..7f5b133 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/model/MbdPaymentOptionRequestProperties.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/model/MbdPaymentOptionRequestProperties.java @@ -9,37 +9,35 @@ import lombok.Data; import lombok.NoArgsConstructor; -/** - * Model class that holds MBD service specific data - */ +/** Model class that holds MBD service specific data */ @Data @Builder @NoArgsConstructor @AllArgsConstructor public class MbdPaymentOptionRequestProperties { - @NotNull(message = "amount is required") - @Schema(description = "MBD amount", requiredMode = Schema.RequiredMode.REQUIRED) - private Long amount; + @NotNull(message = "amount is required") + @Schema(description = "MBD amount", requiredMode = Schema.RequiredMode.REQUIRED) + private Long amount; - @NotBlank - @Schema(description = "Debtor's name", requiredMode = Schema.RequiredMode.REQUIRED) - private String firstName; + @NotBlank + @Schema(description = "Debtor's name", requiredMode = Schema.RequiredMode.REQUIRED) + private String firstName; - @NotBlank - @Schema(description = "Debtor's last name", requiredMode = Schema.RequiredMode.REQUIRED) - private String lastName; + @NotBlank + @Schema(description = "Debtor's last name", requiredMode = Schema.RequiredMode.REQUIRED) + private String lastName; - @NotBlank - @Schema(description = "Debtor's fiscal code", requiredMode = Schema.RequiredMode.REQUIRED) - private String fiscalCode; + @NotBlank + @Schema(description = "Debtor's fiscal code", requiredMode = Schema.RequiredMode.REQUIRED) + private String fiscalCode; - @NotBlank - @Schema(description = "Debtor's residence province", requiredMode = Schema.RequiredMode.REQUIRED) - private String provincialResidence; + @NotBlank + @Schema(description = "Debtor's residence province", requiredMode = Schema.RequiredMode.REQUIRED) + private String provincialResidence; - @NotBlank - @Size(min = 44, max = 44) - @Schema(description = "MBD document's hash", requiredMode = Schema.RequiredMode.REQUIRED) - private String documentHash; -} \ No newline at end of file + @NotBlank + @Size(min = 44, max = 44) + @Schema(description = "MBD document's hash", requiredMode = Schema.RequiredMode.REQUIRED) + private String documentHash; +} diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/model/MbdPaymentOptionResponse.java b/src/main/java/it/gov/pagopa/mbd/gps/service/model/MbdPaymentOptionResponse.java index ec33476..f7530d9 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/model/MbdPaymentOptionResponse.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/model/MbdPaymentOptionResponse.java @@ -2,23 +2,20 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; +import java.util.List; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import java.util.List; - -/** - * Model class that holds MBD GPS response - */ +/** Model class that holds MBD GPS response */ @Data @Builder @AllArgsConstructor @NoArgsConstructor public class MbdPaymentOptionResponse { - @Valid - @Schema(description = "MBD payment option", requiredMode = Schema.RequiredMode.REQUIRED) - private List<@Valid PaymentOption> paymentOption; -} \ No newline at end of file + @Valid + @Schema(description = "MBD payment option", requiredMode = Schema.RequiredMode.REQUIRED) + private List<@Valid PaymentOption> paymentOption; +} diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/model/PaymentOption.java b/src/main/java/it/gov/pagopa/mbd/gps/service/model/PaymentOption.java index c37dec9..59b87f2 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/model/PaymentOption.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/model/PaymentOption.java @@ -5,52 +5,55 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; +import java.time.LocalDateTime; +import java.util.List; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import java.time.LocalDateTime; -import java.util.List; - -/** - * Model class that holds MBD payment option data - */ +/** Model class that holds MBD payment option data */ @Data @Builder @NoArgsConstructor @AllArgsConstructor public class PaymentOption { - @NotBlank - @Schema(description = "Debtor's name", requiredMode = Schema.RequiredMode.REQUIRED) - private String firstName; - - @NotBlank - @Schema(description = "Debtor's last name", requiredMode = Schema.RequiredMode.REQUIRED) - private String lastName; - - @NotNull(message = "amount is required") - @Schema(description = "Payment option's amount", requiredMode = Schema.RequiredMode.REQUIRED) - private Long amount; - - @NotBlank(message = "payment option description is required") - @Size(max = 140) // compliant to paForNode.xsd - @Schema(description = "Payment option's description", requiredMode = Schema.RequiredMode.REQUIRED) - private String description; - - @NotNull(message = "is partial payment is required") - @Schema(description = "Payment option's is partial payment flag", requiredMode = Schema.RequiredMode.REQUIRED) - private Boolean isPartialPayment; - - @NotNull(message = "due date is required") - @Schema(description = "Payment option's due date", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime dueDate; - - @Schema(description = "Payment option's retention date", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime retentionDate; - - @Valid - @Schema(description = "Payment option's transfer list", requiredMode = Schema.RequiredMode.REQUIRED) - private List<@Valid Transfer> transfer; -} \ No newline at end of file + @NotBlank + @Schema(description = "Debtor's name", requiredMode = Schema.RequiredMode.REQUIRED) + private String firstName; + + @NotBlank + @Schema(description = "Debtor's last name", requiredMode = Schema.RequiredMode.REQUIRED) + private String lastName; + + @NotNull(message = "amount is required") + @Schema(description = "Payment option's amount", requiredMode = Schema.RequiredMode.REQUIRED) + private Long amount; + + @NotBlank(message = "payment option description is required") + @Size(max = 140) // compliant to paForNode.xsd + @Schema(description = "Payment option's description", requiredMode = Schema.RequiredMode.REQUIRED) + private String description; + + @NotNull(message = "is partial payment is required") + @Schema( + description = "Payment option's is partial payment flag", + requiredMode = Schema.RequiredMode.REQUIRED) + private Boolean isPartialPayment; + + @NotNull(message = "due date is required") + @Schema(description = "Payment option's due date", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime dueDate; + + @Schema( + description = "Payment option's retention date", + requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime retentionDate; + + @Valid + @Schema( + description = "Payment option's transfer list", + requiredMode = Schema.RequiredMode.REQUIRED) + private List<@Valid Transfer> transfer; +} diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/model/ProblemJson.java b/src/main/java/it/gov/pagopa/mbd/gps/service/model/ProblemJson.java index 0f37bfd..502e9ab 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/model/ProblemJson.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/model/ProblemJson.java @@ -14,7 +14,8 @@ /** * Object returned as response in case of an error. - *

See {@link ErrorHandler} + * + *

See {@link ErrorHandler} */ @Data @Builder(toBuilder = true) @@ -24,17 +25,24 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class ProblemJson { - @JsonProperty("title") - @Schema(description = "A short, summary of the problem type. Written in english and readable for engineers (usually not suited for non technical stakeholders and not localized); example: Service Unavailable") - private String title; + @JsonProperty("title") + @Schema( + description = + "A short, summary of the problem type. Written in english and readable for engineers (usually not suited for non technical stakeholders and not localized); example: Service Unavailable") + private String title; - @JsonProperty("status") - @Schema(example = "200", description = "The HTTP status code generated by the origin server for this occurrence of the problem.") - @Min(100) - @Max(600) - private Integer status; + @JsonProperty("status") + @Schema( + example = "200", + description = + "The HTTP status code generated by the origin server for this occurrence of the problem.") + @Min(100) + @Max(600) + private Integer status; - @JsonProperty("detail") - @Schema(example = "There was an error processing the request", description = "A human readable explanation specific to this occurrence of the problem.") - private String detail; + @JsonProperty("detail") + @Schema( + example = "There was an error processing the request", + description = "A human readable explanation specific to this occurrence of the problem.") + private String detail; } diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/model/Stamp.java b/src/main/java/it/gov/pagopa/mbd/gps/service/model/Stamp.java index 2a4ecf2..cc45e3b 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/model/Stamp.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/model/Stamp.java @@ -9,30 +9,41 @@ import lombok.Data; import lombok.NoArgsConstructor; -/** - * Model class that holds MBD stamp data - */ +/** Model class that holds MBD stamp data */ @Data @Builder @NoArgsConstructor @AllArgsConstructor public class Stamp { - @NotBlank - @Size(max = 72) - @Schema(description = "Document hash type is stBase64Binary72 as described in https://github.com/pagopa/pagopa-api.", requiredMode = Schema.RequiredMode.REQUIRED) - // Stamp generally get as input a base64sha256, that is the SHA256 hash of a given string encoded with Base64. - // It is not equivalent to base64encode(sha256(“test”)), if sha256() returns a hexadecimal representation. - // The result should normally be 44 characters, to be compliant with as-is it was extended to 72 - private String hashDocument; + @NotBlank + @Size(max = 72) + @Schema( + description = + "Document hash type is stBase64Binary72 as described in https://github.com/pagopa/pagopa-api.", + requiredMode = Schema.RequiredMode.REQUIRED) + // Stamp generally get as input a base64sha256, that is the SHA256 hash of a given string encoded + // with Base64. + // It is not equivalent to base64encode(sha256(“test”)), if sha256() returns a hexadecimal + // representation. + // The result should normally be 44 characters, to be compliant with as-is it was extended to 72 + private String hashDocument; - @NotBlank - @Size(min = 2, max = 2) - @Schema(description = "The type of the stamp", minLength = 2, maxLength = 2, requiredMode = Schema.RequiredMode.REQUIRED) - private String stampType; + @NotBlank + @Size(min = 2, max = 2) + @Schema( + description = "The type of the stamp", + minLength = 2, + maxLength = 2, + requiredMode = Schema.RequiredMode.REQUIRED) + private String stampType; - @NotBlank - @Pattern(regexp = "[A-Z]{2}") - @Schema(description = "The province of residence", example = "RM", pattern = "[A-Z]{2,2}", requiredMode = Schema.RequiredMode.REQUIRED) - private String provincialResidence; -} \ No newline at end of file + @NotBlank + @Pattern(regexp = "[A-Z]{2}") + @Schema( + description = "The province of residence", + example = "RM", + pattern = "[A-Z]{2,2}", + requiredMode = Schema.RequiredMode.REQUIRED) + private String provincialResidence; +} diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/model/Transfer.java b/src/main/java/it/gov/pagopa/mbd/gps/service/model/Transfer.java index b452f9d..8acb154 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/model/Transfer.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/model/Transfer.java @@ -10,33 +10,41 @@ import lombok.Data; import lombok.NoArgsConstructor; -/** - * Model class that holds MBD transfer data - */ +/** Model class that holds MBD transfer data */ @Data @Builder @NoArgsConstructor @AllArgsConstructor public class Transfer { - @NotBlank(message = "id transfer is required") - @Schema(description = "Transfer's id", allowableValues = {"1", "2", "3", "4", "5"}, requiredMode = Schema.RequiredMode.REQUIRED) - private String idTransfer; + @NotBlank(message = "id transfer is required") + @Schema( + description = "Transfer's id", + allowableValues = {"1", "2", "3", "4", "5"}, + requiredMode = Schema.RequiredMode.REQUIRED) + private String idTransfer; - @NotNull(message = "amount is required") - @Schema(description = "Transfer's amount", requiredMode = Schema.RequiredMode.REQUIRED) - private Long amount; + @NotNull(message = "amount is required") + @Schema(description = "Transfer's amount", requiredMode = Schema.RequiredMode.REQUIRED) + private Long amount; - @Schema(description = "Fiscal code related to the organization targeted by this transfer.", example = "00000000000") - private String organizationFiscalCode; + @Schema( + description = "Fiscal code related to the organization targeted by this transfer.", + example = "00000000000") + private String organizationFiscalCode; - @NotBlank(message = "remittance information is required") - @Size(max = 140, message = "remittance information must be compliant to EACT FORMATTING RULES, up to 140 chars") - @Schema(description = "Transfer's remittance information", requiredMode = Schema.RequiredMode.REQUIRED) - // https://docs.pagopa.it/saci/specifiche-attuative-dei-codici-identificativi-di-versamento-riversamento-e-rendicontazione/operazione-di-trasferimento-fondi - private String remittanceInformation; // causale + @NotBlank(message = "remittance information is required") + @Size( + max = 140, + message = + "remittance information must be compliant to EACT FORMATTING RULES, up to 140 chars") + @Schema( + description = "Transfer's remittance information", + requiredMode = Schema.RequiredMode.REQUIRED) + // https://docs.pagopa.it/saci/specifiche-attuative-dei-codici-identificativi-di-versamento-riversamento-e-rendicontazione/operazione-di-trasferimento-fondi + private String remittanceInformation; // causale - @Valid - @Schema(description = "Transfer's stamp", requiredMode = Schema.RequiredMode.REQUIRED) - private Stamp stamp; -} \ No newline at end of file + @Valid + @Schema(description = "Transfer's stamp", requiredMode = Schema.RequiredMode.REQUIRED) + private Stamp stamp; +} diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/util/CommonUtility.java b/src/main/java/it/gov/pagopa/mbd/gps/service/util/CommonUtility.java index 9cdba43..32e3ae1 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/util/CommonUtility.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/util/CommonUtility.java @@ -1,52 +1,51 @@ package it.gov.pagopa.mbd.gps.service.util; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - import java.util.Calendar; import java.util.List; import java.util.Optional; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class CommonUtility { - /** - * @param value value to deNullify. - * @return return empty string if value is null - */ - public static String deNull(String value) { - return Optional.ofNullable(value).orElse(""); - } - - /** - * @param value value to deNullify. - * @return return empty string if value is null - */ - public static String deNull(Object value) { - return Optional.ofNullable(value).orElse("").toString(); - } - - /** - * @param value value to deNullify. - * @return return false if value is null - */ - public static Boolean deNull(Boolean value) { - return Optional.ofNullable(value).orElse(false); - } - - /** - * @param headers header of the CSV file - * @param rows data of the CSV file - * @return byte array of the CSV using commas (;) as separator - */ - public static byte[] createCsv(List headers, List> rows) { - var csv = new StringBuilder(); - csv.append(String.join(";", headers)); - rows.forEach(row -> csv.append(System.lineSeparator()).append(String.join(";", row))); - return csv.toString().getBytes(); - } - - public static long getTimelapse(long startTime) { - return Calendar.getInstance().getTimeInMillis() - startTime; - } + /** + * @param value value to deNullify. + * @return return empty string if value is null + */ + public static String deNull(String value) { + return Optional.ofNullable(value).orElse(""); + } + + /** + * @param value value to deNullify. + * @return return empty string if value is null + */ + public static String deNull(Object value) { + return Optional.ofNullable(value).orElse("").toString(); + } + + /** + * @param value value to deNullify. + * @return return false if value is null + */ + public static Boolean deNull(Boolean value) { + return Optional.ofNullable(value).orElse(false); + } + + /** + * @param headers header of the CSV file + * @param rows data of the CSV file + * @return byte array of the CSV using commas (;) as separator + */ + public static byte[] createCsv(List headers, List> rows) { + var csv = new StringBuilder(); + csv.append(String.join(";", headers)); + rows.forEach(row -> csv.append(System.lineSeparator()).append(String.join(";", row))); + return csv.toString().getBytes(); + } + + public static long getTimelapse(long startTime) { + return Calendar.getInstance().getTimeInMillis() - startTime; + } } diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/util/Constants.java b/src/main/java/it/gov/pagopa/mbd/gps/service/util/Constants.java index c56ece4..0e3c68d 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/util/Constants.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/util/Constants.java @@ -5,5 +5,5 @@ @UtilityClass public class Constants { - public static final String HEADER_REQUEST_ID = "X-Request-Id"; + public static final String HEADER_REQUEST_ID = "X-Request-Id"; } diff --git a/src/test/java/it/gov/pagopa/mbd/gps/service/ApplicationTest.java b/src/test/java/it/gov/pagopa/mbd/gps/service/ApplicationTest.java index dda87cb..91215c9 100644 --- a/src/test/java/it/gov/pagopa/mbd/gps/service/ApplicationTest.java +++ b/src/test/java/it/gov/pagopa/mbd/gps/service/ApplicationTest.java @@ -1,16 +1,16 @@ package it.gov.pagopa.mbd.gps.service; +import static org.junit.jupiter.api.Assertions.assertTrue; + import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import static org.junit.jupiter.api.Assertions.assertTrue; - @SpringBootTest class ApplicationTest { - @Test - void contextLoads() { - // check only if the context is loaded - assertTrue(true); - } + @Test + void contextLoads() { + // check only if the context is loaded + assertTrue(true); + } } diff --git a/src/test/java/it/gov/pagopa/mbd/gps/service/OpenApiGenerationTest.java b/src/test/java/it/gov/pagopa/mbd/gps/service/OpenApiGenerationTest.java index 8fbba35..67586b3 100644 --- a/src/test/java/it/gov/pagopa/mbd/gps/service/OpenApiGenerationTest.java +++ b/src/test/java/it/gov/pagopa/mbd/gps/service/OpenApiGenerationTest.java @@ -1,6 +1,12 @@ package it.gov.pagopa.mbd.gps.service; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; + import com.fasterxml.jackson.databind.ObjectMapper; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -10,41 +16,32 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; - @SpringBootTest(classes = Application.class) @AutoConfigureMockMvc class OpenApiGenerationTest { - @Autowired - ObjectMapper objectMapper; + @Autowired ObjectMapper objectMapper; - @Autowired - private MockMvc mvc; + @Autowired private MockMvc mvc; - @Test - void swaggerSpringPlugin() throws Exception { - mvc.perform(MockMvcRequestBuilders.get("/v3/api-docs").accept(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()) - .andDo( - result -> { - assertNotNull(result); - assertNotNull(result.getResponse()); - final String content = result.getResponse().getContentAsString(); - assertFalse(content.isBlank()); - assertFalse(content.contains("${"), "Generated swagger contains placeholders"); - Object swagger = - objectMapper.readValue(result.getResponse().getContentAsString(), Object.class); - String formatted = - objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(swagger); - Path basePath = Paths.get("openapi/"); - Files.createDirectories(basePath); - Files.write(basePath.resolve("openapi.json"), formatted.getBytes()); - }); - } + @Test + void swaggerSpringPlugin() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/v3/api-docs").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().is2xxSuccessful()) + .andDo( + result -> { + assertNotNull(result); + assertNotNull(result.getResponse()); + final String content = result.getResponse().getContentAsString(); + assertFalse(content.isBlank()); + assertFalse(content.contains("${"), "Generated swagger contains placeholders"); + Object swagger = + objectMapper.readValue(result.getResponse().getContentAsString(), Object.class); + String formatted = + objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(swagger); + Path basePath = Paths.get("openapi/"); + Files.createDirectories(basePath); + Files.write(basePath.resolve("openapi.json"), formatted.getBytes()); + }); + } } diff --git a/src/test/java/it/gov/pagopa/mbd/gps/service/controller/HomeControllerTest.java b/src/test/java/it/gov/pagopa/mbd/gps/service/controller/HomeControllerTest.java index df082a9..56db799 100644 --- a/src/test/java/it/gov/pagopa/mbd/gps/service/controller/HomeControllerTest.java +++ b/src/test/java/it/gov/pagopa/mbd/gps/service/controller/HomeControllerTest.java @@ -1,28 +1,27 @@ package it.gov.pagopa.mbd.gps.service.controller; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.web.servlet.MockMvc; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - @AutoConfigureMockMvc @SpringBootTest class HomeControllerTest { - @Autowired - private MockMvc mvc; + @Autowired private MockMvc mvc; - @Test - void healthCheckTestSuccess() throws Exception { - mvc.perform(get("/info")).andExpect(status().isOk()); - } + @Test + void healthCheckTestSuccess() throws Exception { + mvc.perform(get("/info")).andExpect(status().isOk()); + } - @Test - void homeTestSuccess() throws Exception { - mvc.perform(get("")).andExpect(status().is3xxRedirection()); - } -} \ No newline at end of file + @Test + void homeTestSuccess() throws Exception { + mvc.perform(get("")).andExpect(status().is3xxRedirection()); + } +} diff --git a/src/test/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsControllerTest.java b/src/test/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsControllerTest.java index 1a40e4f..69f6fed 100644 --- a/src/test/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsControllerTest.java +++ b/src/test/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsControllerTest.java @@ -1,10 +1,17 @@ package it.gov.pagopa.mbd.gps.service.controller; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + import com.fasterxml.jackson.databind.ObjectMapper; -import it.gov.pagopa.mbd.gps.service.model.MbdPaymentOptionRequestProperties; -import it.gov.pagopa.mbd.gps.service.model.PaymentOption; import it.gov.pagopa.mbd.gps.service.model.MbdPaymentOptionRequest; +import it.gov.pagopa.mbd.gps.service.model.MbdPaymentOptionRequestProperties; import it.gov.pagopa.mbd.gps.service.model.MbdPaymentOptionResponse; +import it.gov.pagopa.mbd.gps.service.model.PaymentOption; import it.gov.pagopa.mbd.gps.service.model.Transfer; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -14,160 +21,157 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - @AutoConfigureMockMvc @SpringBootTest class MbdGpsControllerTest { - @Autowired - private MockMvc mvc; - - @Autowired - private ObjectMapper objectMapper; - - @Test - void createMdbPaymentOptionTestSuccess() throws Exception { - MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); - - MvcResult result = mvc.perform(post("/mbd/paymentOption") - .content(objectMapper.writeValueAsString(request)) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isCreated()) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) - .andReturn(); - - String json = result.getResponse().getContentAsString(); - - assertNotNull(json); - - MbdPaymentOptionResponse response = objectMapper.readValue(json, MbdPaymentOptionResponse.class); - - assertNotNull(response); - assertNotNull(response.getPaymentOption()); - assertEquals(1, response.getPaymentOption().size()); - - PaymentOption paymentOption = response.getPaymentOption().get(0); - assertEquals(request.getProperties().getFirstName(), paymentOption.getFirstName()); - assertEquals(request.getProperties().getLastName(), paymentOption.getLastName()); - assertEquals(request.getProperties().getAmount(), paymentOption.getAmount()); - assertNotNull(paymentOption.getDescription()); - assertNotNull(paymentOption.getDueDate()); - assertNotNull(paymentOption.getRetentionDate()); - assertFalse(paymentOption.getIsPartialPayment()); - assertNotNull(paymentOption.getTransfer()); - assertEquals(1, paymentOption.getTransfer().size()); - - Transfer transfer = paymentOption.getTransfer().get(0); - assertEquals(request.getProperties().getAmount(), transfer.getAmount()); - assertEquals(request.getProperties().getFiscalCode(), transfer.getOrganizationFiscalCode()); - assertEquals("1", transfer.getIdTransfer()); - assertNotNull(transfer.getRemittanceInformation()); - assertNotNull(transfer.getStamp()); - assertEquals(request.getProperties().getProvincialResidence(), transfer.getStamp().getProvincialResidence()); - assertEquals(request.getProperties().getDocumentHash(), transfer.getStamp().getHashDocument()); - assertEquals("st", transfer.getStamp().getStampType()); - } - - @Test - void createMdbPaymentOptionTestFailAmountMissing() throws Exception { - MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); - request.getProperties().setAmount(null); - - mvc.perform(post("/mbd/paymentOption") - .content(objectMapper.writeValueAsString(request)) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().is4xxClientError()); - - } - - @Test - void createMdbPaymentOptionTestFailFirstNameMissing() throws Exception { - MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); - request.getProperties().setFirstName(null); - - mvc.perform(post("/mbd/paymentOption") - .content(objectMapper.writeValueAsString(request)) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().is4xxClientError()); - - } - - @Test - void createMdbPaymentOptionTestFailLastNameMissing() throws Exception { - MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); - request.getProperties().setLastName(null); - - mvc.perform(post("/mbd/paymentOption") - .content(objectMapper.writeValueAsString(request)) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().is4xxClientError()); - - } - - @Test - void createMdbPaymentOptionTestFailFiscalCodeMissing() throws Exception { - MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); - request.getProperties().setFiscalCode(null); - - mvc.perform(post("/mbd/paymentOption") - .content(objectMapper.writeValueAsString(request)) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().is4xxClientError()); - - } - - @Test - void createMdbPaymentOptionTestFailProvincialResidenceMissing() throws Exception { - MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); - request.getProperties().setProvincialResidence(null); - - mvc.perform(post("/mbd/paymentOption") - .content(objectMapper.writeValueAsString(request)) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().is4xxClientError()); - - } - - @Test - void createMdbPaymentOptionTestFailDocumentHashMissing() throws Exception { - MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); - request.getProperties().setDocumentHash(null); - - mvc.perform(post("/mbd/paymentOption") - .content(objectMapper.writeValueAsString(request)) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().is4xxClientError()); - - } - - @Test - void createMdbPaymentOptionTestFailDocumentHashWrongSize() throws Exception { - MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); - request.getProperties().setDocumentHash("asdfsdf"); - - mvc.perform(post("/mbd/paymentOption") - .content(objectMapper.writeValueAsString(request)) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().is4xxClientError()); - - } - - private MbdPaymentOptionRequest buildMdbPaymentOptionRequest() { - return MbdPaymentOptionRequest.builder() - .properties(MbdPaymentOptionRequestProperties.builder() - .amount(16L) - .firstName("Mario") - .lastName("Rossi") - .fiscalCode("0000000000000000") - .provincialResidence("AS") - .documentHash("1trA5qyjSZNwiwtGG46dyjRpL16TFgGCFvnfFzQrFHbB") - .build()) - .build(); - } -} \ No newline at end of file + @Autowired private MockMvc mvc; + + @Autowired private ObjectMapper objectMapper; + + @Test + void createMdbPaymentOptionTestSuccess() throws Exception { + MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + + MvcResult result = + mvc.perform( + post("/mbd/paymentOption") + .content(objectMapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isCreated()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andReturn(); + + String json = result.getResponse().getContentAsString(); + + assertNotNull(json); + + MbdPaymentOptionResponse response = + objectMapper.readValue(json, MbdPaymentOptionResponse.class); + + assertNotNull(response); + assertNotNull(response.getPaymentOption()); + assertEquals(1, response.getPaymentOption().size()); + + PaymentOption paymentOption = response.getPaymentOption().get(0); + assertEquals(request.getProperties().getFirstName(), paymentOption.getFirstName()); + assertEquals(request.getProperties().getLastName(), paymentOption.getLastName()); + assertEquals(request.getProperties().getAmount(), paymentOption.getAmount()); + assertNotNull(paymentOption.getDescription()); + assertNotNull(paymentOption.getDueDate()); + assertNotNull(paymentOption.getRetentionDate()); + assertFalse(paymentOption.getIsPartialPayment()); + assertNotNull(paymentOption.getTransfer()); + assertEquals(1, paymentOption.getTransfer().size()); + + Transfer transfer = paymentOption.getTransfer().get(0); + assertEquals(request.getProperties().getAmount(), transfer.getAmount()); + assertEquals(request.getProperties().getFiscalCode(), transfer.getOrganizationFiscalCode()); + assertEquals("1", transfer.getIdTransfer()); + assertNotNull(transfer.getRemittanceInformation()); + assertNotNull(transfer.getStamp()); + assertEquals( + request.getProperties().getProvincialResidence(), + transfer.getStamp().getProvincialResidence()); + assertEquals(request.getProperties().getDocumentHash(), transfer.getStamp().getHashDocument()); + assertEquals("st", transfer.getStamp().getStampType()); + } + + @Test + void createMdbPaymentOptionTestFailAmountMissing() throws Exception { + MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + request.getProperties().setAmount(null); + + mvc.perform( + post("/mbd/paymentOption") + .content(objectMapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()); + } + + @Test + void createMdbPaymentOptionTestFailFirstNameMissing() throws Exception { + MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + request.getProperties().setFirstName(null); + + mvc.perform( + post("/mbd/paymentOption") + .content(objectMapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()); + } + + @Test + void createMdbPaymentOptionTestFailLastNameMissing() throws Exception { + MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + request.getProperties().setLastName(null); + + mvc.perform( + post("/mbd/paymentOption") + .content(objectMapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()); + } + + @Test + void createMdbPaymentOptionTestFailFiscalCodeMissing() throws Exception { + MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + request.getProperties().setFiscalCode(null); + + mvc.perform( + post("/mbd/paymentOption") + .content(objectMapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()); + } + + @Test + void createMdbPaymentOptionTestFailProvincialResidenceMissing() throws Exception { + MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + request.getProperties().setProvincialResidence(null); + + mvc.perform( + post("/mbd/paymentOption") + .content(objectMapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()); + } + + @Test + void createMdbPaymentOptionTestFailDocumentHashMissing() throws Exception { + MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + request.getProperties().setDocumentHash(null); + + mvc.perform( + post("/mbd/paymentOption") + .content(objectMapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()); + } + + @Test + void createMdbPaymentOptionTestFailDocumentHashWrongSize() throws Exception { + MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + request.getProperties().setDocumentHash("asdfsdf"); + + mvc.perform( + post("/mbd/paymentOption") + .content(objectMapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()); + } + + private MbdPaymentOptionRequest buildMdbPaymentOptionRequest() { + return MbdPaymentOptionRequest.builder() + .properties( + MbdPaymentOptionRequestProperties.builder() + .amount(16L) + .firstName("Mario") + .lastName("Rossi") + .fiscalCode("0000000000000000") + .provincialResidence("AS") + .documentHash("1trA5qyjSZNwiwtGG46dyjRpL16TFgGCFvnfFzQrFHbB") + .build()) + .build(); + } +} From 5990882a3a6e9f8ca0c2de344edee16766be2790 Mon Sep 17 00:00:00 2001 From: giomella Date: Wed, 4 Dec 2024 14:31:04 +0100 Subject: [PATCH 22/29] [PPANTT-191] exclude util from coverage --- .github/workflows/ci_code_review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_code_review.yml b/.github/workflows/ci_code_review.yml index 108f708..aa73dca 100644 --- a/.github/workflows/ci_code_review.yml +++ b/.github/workflows/ci_code_review.yml @@ -40,7 +40,7 @@ jobs: github_token: ${{ secrets.GITHUB_TOKEN }} sonar_token: ${{ secrets.SONAR_TOKEN }} project_key: ${{env.PROJECT_KEY}} - coverage_exclusions: "**/config/*,**/*Mock*,**/model/**,**/entity/*,**/exception/**" + coverage_exclusions: "**/config/*,**/*Mock*,**/model/**,**/entity/*,**/exception/**,**/util/**" cpd_exclusions: "**/model/**,**/entity/*" java_version: 17 From 3dd976a2e407627f4ab7bb6a1fa29ffa33b0033b Mon Sep 17 00:00:00 2001 From: giomella Date: Wed, 4 Dec 2024 14:41:29 +0100 Subject: [PATCH 23/29] [PPANTT-191] updated helm with service monitor and set pod as burstable --- helm/values-dev.yaml | 13 +++++++++++-- helm/values-prod.yaml | 13 +++++++++++-- helm/values-uat.yaml | 13 +++++++++++-- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/helm/values-dev.yaml b/helm/values-dev.yaml index 342f98f..c042c2a 100644 --- a/helm/values-dev.yaml +++ b/helm/values-dev.yaml @@ -24,6 +24,15 @@ microservice-chart: periodSeconds: 10 deployment: create: true + serviceMonitor: + create: true + endpoints: + - interval: 10s #jmx-exporter + targetPort: 12345 + path: /metrics + ports: + - 8080 + - 12345 #jmx-exporter service: create: true type: ClusterIP @@ -53,8 +62,8 @@ microservice-chart: memory: "512Mi" cpu: "0.25" limits: - memory: "512Mi" - cpu: "0.25" + memory: "768Mi" + cpu: "0.5" autoscaling: enable: true minReplica: 1 diff --git a/helm/values-prod.yaml b/helm/values-prod.yaml index c06413c..3e3ca08 100644 --- a/helm/values-prod.yaml +++ b/helm/values-prod.yaml @@ -24,6 +24,15 @@ microservice-chart: periodSeconds: 10 deployment: create: true + serviceMonitor: + create: true + endpoints: + - interval: 10s #jmx-exporter + targetPort: 12345 + path: /metrics + ports: + - 8080 + - 12345 #jmx-exporter service: create: true type: ClusterIP @@ -53,8 +62,8 @@ microservice-chart: memory: "512Mi" cpu: "0.25" limits: - memory: "512Mi" - cpu: "0.25" + memory: "768Mi" + cpu: "0.5" autoscaling: enable: true minReplica: 3 diff --git a/helm/values-uat.yaml b/helm/values-uat.yaml index cabf580..4b63218 100644 --- a/helm/values-uat.yaml +++ b/helm/values-uat.yaml @@ -24,6 +24,15 @@ microservice-chart: periodSeconds: 10 deployment: create: true + serviceMonitor: + create: true + endpoints: + - interval: 10s #jmx-exporter + targetPort: 12345 + path: /metrics + ports: + - 8080 + - 12345 #jmx-exporter service: create: true type: ClusterIP @@ -53,8 +62,8 @@ microservice-chart: memory: "512Mi" cpu: "0.25" limits: - memory: "512Mi" - cpu: "0.25" + memory: "768Mi" + cpu: "0.5" autoscaling: enable: true minReplica: 3 From 7a623920d7d3b422a1580df0ed73fbce2c96e982 Mon Sep 17 00:00:00 2001 From: gioelemella <128155546+gioelemella@users.noreply.github.com> Date: Wed, 4 Dec 2024 14:45:15 +0100 Subject: [PATCH 24/29] Update src/main/java/it/gov/pagopa/mbd/gps/service/model/ProblemJson.java Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .../java/it/gov/pagopa/mbd/gps/service/model/ProblemJson.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/model/ProblemJson.java b/src/main/java/it/gov/pagopa/mbd/gps/service/model/ProblemJson.java index 502e9ab..424e475 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/model/ProblemJson.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/model/ProblemJson.java @@ -28,7 +28,9 @@ public class ProblemJson { @JsonProperty("title") @Schema( description = - "A short, summary of the problem type. Written in english and readable for engineers (usually not suited for non technical stakeholders and not localized); example: Service Unavailable") + "A short, summary of the problem type. Written in english and readable for engineers" + + " (usually not suited for non technical stakeholders and not localized); example:" + + " Service Unavailable") private String title; @JsonProperty("status") From 97628f15d2fdeb8ac9341cec2dc83c100bc6bbe7 Mon Sep 17 00:00:00 2001 From: gioelemella <128155546+gioelemella@users.noreply.github.com> Date: Wed, 4 Dec 2024 14:45:22 +0100 Subject: [PATCH 25/29] Update src/main/java/it/gov/pagopa/mbd/gps/service/model/Stamp.java Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- src/main/java/it/gov/pagopa/mbd/gps/service/model/Stamp.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/model/Stamp.java b/src/main/java/it/gov/pagopa/mbd/gps/service/model/Stamp.java index cc45e3b..7a2a035 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/model/Stamp.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/model/Stamp.java @@ -20,7 +20,8 @@ public class Stamp { @Size(max = 72) @Schema( description = - "Document hash type is stBase64Binary72 as described in https://github.com/pagopa/pagopa-api.", + "Document hash type is stBase64Binary72 as described in" + + " https://github.com/pagopa/pagopa-api.", requiredMode = Schema.RequiredMode.REQUIRED) // Stamp generally get as input a base64sha256, that is the SHA256 hash of a given string encoded // with Base64. From 7acce6bcd72e2a0e26528a9fa395c281d30e90a1 Mon Sep 17 00:00:00 2001 From: gioelemella <128155546+gioelemella@users.noreply.github.com> Date: Wed, 4 Dec 2024 14:45:28 +0100 Subject: [PATCH 26/29] Update src/main/java/it/gov/pagopa/mbd/gps/service/config/MappingsConfiguration.java Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .../pagopa/mbd/gps/service/config/MappingsConfiguration.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/config/MappingsConfiguration.java b/src/main/java/it/gov/pagopa/mbd/gps/service/config/MappingsConfiguration.java index b2d0494..c4c998a 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/config/MappingsConfiguration.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/config/MappingsConfiguration.java @@ -13,8 +13,7 @@ public class MappingsConfiguration { @Bean ModelMapper modelMapper( - ConvertMbdPaymentOptionRequestToMbdPaymentOptionResponse mdbPaymentOptionResponseConverter - ) { + ConvertMbdPaymentOptionRequestToMbdPaymentOptionResponse mdbPaymentOptionResponseConverter) { ModelMapper mapper = new ModelMapper(); mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); From 0fd74dd6767a13ef82eb54d120789f92956b0a6c Mon Sep 17 00:00:00 2001 From: giomella Date: Wed, 4 Dec 2024 15:08:05 +0100 Subject: [PATCH 27/29] [PPANTT-191] configured opex --- .opex/env/prod/backend.tfvars | 2 +- .opex/env/prod/config.yaml | 9 ++++++--- .opex/env/prod/terraform.tfvars | 3 +-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.opex/env/prod/backend.tfvars b/.opex/env/prod/backend.tfvars index ae0e6e4..8b5cd7b 100644 --- a/.opex/env/prod/backend.tfvars +++ b/.opex/env/prod/backend.tfvars @@ -1,4 +1,4 @@ resource_group_name = "io-infra-rg" storage_account_name = "pagopainfraterraformprod" container_name = "azurermstate" -key = "opex..terraform.tfstate" #TODO +key = "pagopa-gps-mbd-service.tfstate" diff --git a/.opex/env/prod/config.yaml b/.opex/env/prod/config.yaml index 80a9d54..8201e8f 100644 --- a/.opex/env/prod/config.yaml +++ b/.opex/env/prod/config.yaml @@ -1,10 +1,13 @@ oa3_spec: ./openapi/openapi.json # If start with http the file would be downloaded from the internet -name: opex_ # TODO -location: West Europe +name: opex_pagopa-gps-mbd-service +location: Italy North timespan: 5m # Default, a number or a timespan https://docs.microsoft.com/en-us/azure/data-explorer/kusto/query/scalar-data-types/timespan +# public data_source data_source: /subscriptions/b9fc9419-6097-45fe-9f74-ba0641c91912/resourceGroups/pagopa-p-vnet-rg/providers/Microsoft.Network/applicationGateways/pagopa-p-app-gw +# private data_source #data_source: /subscriptions/b9fc9419-6097-45fe-9f74-ba0641c91912/resourceGroups/pagopa-p-api-rg/providers/Microsoft.ApiManagement/service/pagopa-p-apim -#resource_type: api-management + +#resource_type: api-management # default is app-gw. uncomment for api-management action_groups: - /subscriptions/b9fc9419-6097-45fe-9f74-ba0641c91912/resourceGroups/pagopa-p-monitor-rg/providers/microsoft.insights/actionGroups/PagoPA - /subscriptions/b9fc9419-6097-45fe-9f74-ba0641c91912/resourceGroups/pagopa-p-monitor-rg/providers/microsoft.insights/actionGroups/SlackPagoPA diff --git a/.opex/env/prod/terraform.tfvars b/.opex/env/prod/terraform.tfvars index 1445485..d498227 100644 --- a/.opex/env/prod/terraform.tfvars +++ b/.opex/env/prod/terraform.tfvars @@ -1,11 +1,10 @@ prefix = "pagopa" env_short = "p" - tags = { CreatedBy = "Terraform" Environment = "Prod" Owner = "pagoPA" - Source = "https://github.com/pagopa/your-repository" # TODO + Source = "https://github.com/pagopa/pagopa-gps-mbd-service" CostCenter = "TS310 - PAGAMENTI & SERVIZI" } From ab5a1f1c655a532a7d658e85fa619a3fc9311eb4 Mon Sep 17 00:00:00 2001 From: giomella Date: Wed, 4 Dec 2024 15:15:21 +0100 Subject: [PATCH 28/29] [PPANTT-191] fix --- openapi/openapi.json | 4 +-- .../service/controller/MbdGpsController.java | 4 +-- .../controller/MbdGpsControllerTest.java | 34 +++++++++---------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/openapi/openapi.json b/openapi/openapi.json index 1ce20d3..c9043b2 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -85,7 +85,7 @@ } ], "post": { - "operationId": "createMdbPaymentOption", + "operationId": "buildMdbPaymentOption", "requestBody": { "content": { "application/json": { @@ -215,7 +215,7 @@ "ApiKey": [] } ], - "summary": "Create MBD payment option", + "summary": "Build MBD payment option model", "tags": [ "MBD GPS" ] diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsController.java b/src/main/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsController.java index c72bb1e..30c1fb1 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsController.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsController.java @@ -81,9 +81,9 @@ public MbdGpsController(ModelMapper modelMapper) { schema = @Schema(implementation = ProblemJson.class))) }) @Operation( - summary = "Create MBD payment option", + summary = "Build MBD payment option model", security = {@SecurityRequirement(name = "ApiKey")}) - public @Valid MbdPaymentOptionResponse createMdbPaymentOption( + public @Valid MbdPaymentOptionResponse buildMdbPaymentOption( @RequestBody @NotNull @Valid MbdPaymentOptionRequest mbdPaymentOptionRequest) { return this.modelMapper.map(mbdPaymentOptionRequest, MbdPaymentOptionResponse.class); } diff --git a/src/test/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsControllerTest.java b/src/test/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsControllerTest.java index 69f6fed..30e4084 100644 --- a/src/test/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsControllerTest.java +++ b/src/test/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsControllerTest.java @@ -30,8 +30,8 @@ class MbdGpsControllerTest { @Autowired private ObjectMapper objectMapper; @Test - void createMdbPaymentOptionTestSuccess() throws Exception { - MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + void buildMbdPaymentOptionTestSuccess() throws Exception { + MbdPaymentOptionRequest request = buildMbdPaymentOptionRequest(); MvcResult result = mvc.perform( @@ -78,8 +78,8 @@ void createMdbPaymentOptionTestSuccess() throws Exception { } @Test - void createMdbPaymentOptionTestFailAmountMissing() throws Exception { - MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + void buildMbdPaymentOptionTestFailAmountMissing() throws Exception { + MbdPaymentOptionRequest request = buildMbdPaymentOptionRequest(); request.getProperties().setAmount(null); mvc.perform( @@ -90,8 +90,8 @@ void createMdbPaymentOptionTestFailAmountMissing() throws Exception { } @Test - void createMdbPaymentOptionTestFailFirstNameMissing() throws Exception { - MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + void buildMbdPaymentOptionTestFailFirstNameMissing() throws Exception { + MbdPaymentOptionRequest request = buildMbdPaymentOptionRequest(); request.getProperties().setFirstName(null); mvc.perform( @@ -102,8 +102,8 @@ void createMdbPaymentOptionTestFailFirstNameMissing() throws Exception { } @Test - void createMdbPaymentOptionTestFailLastNameMissing() throws Exception { - MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + void buildMbdPaymentOptionTestFailLastNameMissing() throws Exception { + MbdPaymentOptionRequest request = buildMbdPaymentOptionRequest(); request.getProperties().setLastName(null); mvc.perform( @@ -114,8 +114,8 @@ void createMdbPaymentOptionTestFailLastNameMissing() throws Exception { } @Test - void createMdbPaymentOptionTestFailFiscalCodeMissing() throws Exception { - MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + void buildMbdPaymentOptionTestFailFiscalCodeMissing() throws Exception { + MbdPaymentOptionRequest request = buildMbdPaymentOptionRequest(); request.getProperties().setFiscalCode(null); mvc.perform( @@ -126,8 +126,8 @@ void createMdbPaymentOptionTestFailFiscalCodeMissing() throws Exception { } @Test - void createMdbPaymentOptionTestFailProvincialResidenceMissing() throws Exception { - MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + void buildMbdPaymentOptionTestFailProvincialResidenceMissing() throws Exception { + MbdPaymentOptionRequest request = buildMbdPaymentOptionRequest(); request.getProperties().setProvincialResidence(null); mvc.perform( @@ -138,8 +138,8 @@ void createMdbPaymentOptionTestFailProvincialResidenceMissing() throws Exception } @Test - void createMdbPaymentOptionTestFailDocumentHashMissing() throws Exception { - MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + void buildMbdPaymentOptionTestFailDocumentHashMissing() throws Exception { + MbdPaymentOptionRequest request = buildMbdPaymentOptionRequest(); request.getProperties().setDocumentHash(null); mvc.perform( @@ -150,8 +150,8 @@ void createMdbPaymentOptionTestFailDocumentHashMissing() throws Exception { } @Test - void createMdbPaymentOptionTestFailDocumentHashWrongSize() throws Exception { - MbdPaymentOptionRequest request = buildMdbPaymentOptionRequest(); + void buildMbdPaymentOptionTestFailDocumentHashWrongSize() throws Exception { + MbdPaymentOptionRequest request = buildMbdPaymentOptionRequest(); request.getProperties().setDocumentHash("asdfsdf"); mvc.perform( @@ -161,7 +161,7 @@ void createMdbPaymentOptionTestFailDocumentHashWrongSize() throws Exception { .andExpect(status().is4xxClientError()); } - private MbdPaymentOptionRequest buildMdbPaymentOptionRequest() { + private MbdPaymentOptionRequest buildMbdPaymentOptionRequest() { return MbdPaymentOptionRequest.builder() .properties( MbdPaymentOptionRequestProperties.builder() From 7a2df6ddf1aa3630e35d20e915cff3f15428c0c9 Mon Sep 17 00:00:00 2001 From: giomella Date: Wed, 4 Dec 2024 15:17:31 +0100 Subject: [PATCH 29/29] [PPANTT-191] fix --- openapi/openapi.json | 2 +- .../gov/pagopa/mbd/gps/service/controller/MbdGpsController.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openapi/openapi.json b/openapi/openapi.json index c9043b2..32b2306 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -85,7 +85,7 @@ } ], "post": { - "operationId": "buildMdbPaymentOption", + "operationId": "buildMbdPaymentOption", "requestBody": { "content": { "application/json": { diff --git a/src/main/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsController.java b/src/main/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsController.java index 30c1fb1..38379f3 100644 --- a/src/main/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsController.java +++ b/src/main/java/it/gov/pagopa/mbd/gps/service/controller/MbdGpsController.java @@ -83,7 +83,7 @@ public MbdGpsController(ModelMapper modelMapper) { @Operation( summary = "Build MBD payment option model", security = {@SecurityRequirement(name = "ApiKey")}) - public @Valid MbdPaymentOptionResponse buildMdbPaymentOption( + public @Valid MbdPaymentOptionResponse buildMbdPaymentOption( @RequestBody @NotNull @Valid MbdPaymentOptionRequest mbdPaymentOptionRequest) { return this.modelMapper.map(mbdPaymentOptionRequest, MbdPaymentOptionResponse.class); }