From e4c27c6afac12488338b887983f67c61289191f9 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Fri, 14 Nov 2025 16:14:23 +0100 Subject: [PATCH] Harmonize exceptions handling --- pom.xml | 1 + .../server/PropertyServerNameProvider.java | 29 +++++++++++++ .../RestResponseEntityExceptionHandler.java | 43 +++++++++++++++++++ .../error/VoltageInitBusinessErrorCode.java | 17 ++++++++ .../server/error/VoltageInitException.java | 15 ++++++- .../service/VoltageInitResultContext.java | 1 + .../service/parameters/FilterService.java | 3 +- .../PropertyServerNameProviderTest.java | 23 ++++++++++ .../VoltageInitBusinessErrorCodeTest.java | 24 +++++++++++ .../service/parameters/ParametersTest.java | 3 +- 10 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/gridsuite/voltageinit/server/PropertyServerNameProvider.java create mode 100644 src/main/java/org/gridsuite/voltageinit/server/error/RestResponseEntityExceptionHandler.java create mode 100644 src/main/java/org/gridsuite/voltageinit/server/error/VoltageInitBusinessErrorCode.java create mode 100644 src/test/java/org/gridsuite/voltageinit/server/PropertyServerNameProviderTest.java create mode 100644 src/test/java/org/gridsuite/voltageinit/server/VoltageInitBusinessErrorCodeTest.java diff --git a/pom.xml b/pom.xml index 158700d..63ab523 100644 --- a/pom.xml +++ b/pom.xml @@ -181,6 +181,7 @@ org.gridsuite gridsuite-computation + 1.6.0-SNAPSHOT com.powsybl diff --git a/src/main/java/org/gridsuite/voltageinit/server/PropertyServerNameProvider.java b/src/main/java/org/gridsuite/voltageinit/server/PropertyServerNameProvider.java new file mode 100644 index 0000000..5a40230 --- /dev/null +++ b/src/main/java/org/gridsuite/voltageinit/server/PropertyServerNameProvider.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.voltageinit.server; + +import com.powsybl.ws.commons.error.ServerNameProvider; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * @author Hugo Marcellin + */ +@Component +public class PropertyServerNameProvider implements ServerNameProvider { + + private final String name; + + public PropertyServerNameProvider(@Value("${spring.application.name:voltage-init-server}") String name) { + this.name = name; + } + + @Override + public String serverName() { + return name; + } +} diff --git a/src/main/java/org/gridsuite/voltageinit/server/error/RestResponseEntityExceptionHandler.java b/src/main/java/org/gridsuite/voltageinit/server/error/RestResponseEntityExceptionHandler.java new file mode 100644 index 0000000..c9633ad --- /dev/null +++ b/src/main/java/org/gridsuite/voltageinit/server/error/RestResponseEntityExceptionHandler.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.gridsuite.voltageinit.server.error; + +import com.powsybl.ws.commons.error.AbstractBaseRestExceptionHandler; +import com.powsybl.ws.commons.error.ServerNameProvider; +import lombok.NonNull; +import org.gridsuite.computation.ComputationBusinessErrorCode; +import org.gridsuite.computation.ComputationException; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ControllerAdvice; + +/** + * @author Hugo Marcellin + */ +@ControllerAdvice +public class RestResponseEntityExceptionHandler extends AbstractBaseRestExceptionHandler { + + protected RestResponseEntityExceptionHandler(ServerNameProvider serverNameProvider) { + super(serverNameProvider); + } + + @Override + protected @NonNull ComputationBusinessErrorCode getBusinessCode(ComputationException e) { + return e.getBusinessErrorCode(); + } + + @Override + protected HttpStatus mapStatus(ComputationBusinessErrorCode businessErrorCode) { + return switch (businessErrorCode) { + case RESULT_NOT_FOUND, NETWORK_NOT_FOUND, PARAMETERS_NOT_FOUND -> HttpStatus.NOT_FOUND; + case INVALID_FILTER_FORMAT, + INVALID_SORT_FORMAT, + INVALID_FILTER -> HttpStatus.BAD_REQUEST; + default -> HttpStatus.INTERNAL_SERVER_ERROR; + }; + } +} diff --git a/src/main/java/org/gridsuite/voltageinit/server/error/VoltageInitBusinessErrorCode.java b/src/main/java/org/gridsuite/voltageinit/server/error/VoltageInitBusinessErrorCode.java new file mode 100644 index 0000000..d1086f1 --- /dev/null +++ b/src/main/java/org/gridsuite/voltageinit/server/error/VoltageInitBusinessErrorCode.java @@ -0,0 +1,17 @@ +package org.gridsuite.voltageinit.server.error; + +import com.powsybl.ws.commons.error.BusinessErrorCode; + +public enum VoltageInitBusinessErrorCode implements BusinessErrorCode { + MISSING_FILTER("voltageInit.missingFilter"); + + private final String code; + + VoltageInitBusinessErrorCode(String code) { + this.code = code; + } + + public String value() { + return code; + } +} diff --git a/src/main/java/org/gridsuite/voltageinit/server/error/VoltageInitException.java b/src/main/java/org/gridsuite/voltageinit/server/error/VoltageInitException.java index 408e6ea..30c5300 100644 --- a/src/main/java/org/gridsuite/voltageinit/server/error/VoltageInitException.java +++ b/src/main/java/org/gridsuite/voltageinit/server/error/VoltageInitException.java @@ -6,14 +6,25 @@ */ package org.gridsuite.voltageinit.server.error; +import com.powsybl.ws.commons.error.AbstractBusinessException; +import lombok.NonNull; + import java.util.Objects; /** * @author Mohamed Ben-rejeb {@literal } */ -public class VoltageInitException extends RuntimeException { +public class VoltageInitException extends AbstractBusinessException { + + private final VoltageInitBusinessErrorCode errorCode; - public VoltageInitException(String message) { + public VoltageInitException(VoltageInitBusinessErrorCode errorCode, String message) { super(Objects.requireNonNull(message, "message must not be null")); + this.errorCode = Objects.requireNonNull(errorCode, "errorCode must not be null"); + } + + @Override + public @NonNull VoltageInitBusinessErrorCode getBusinessErrorCode() { + return errorCode; } } diff --git a/src/main/java/org/gridsuite/voltageinit/server/service/VoltageInitResultContext.java b/src/main/java/org/gridsuite/voltageinit/server/service/VoltageInitResultContext.java index d0c866e..761b9ee 100644 --- a/src/main/java/org/gridsuite/voltageinit/server/service/VoltageInitResultContext.java +++ b/src/main/java/org/gridsuite/voltageinit/server/service/VoltageInitResultContext.java @@ -89,3 +89,4 @@ protected Map getSpecificMsgHeaders(ObjectMapper objectMapper) { return specificMsgHeaders; } } + diff --git a/src/main/java/org/gridsuite/voltageinit/server/service/parameters/FilterService.java b/src/main/java/org/gridsuite/voltageinit/server/service/parameters/FilterService.java index 262cbbd..97dbf5c 100644 --- a/src/main/java/org/gridsuite/voltageinit/server/service/parameters/FilterService.java +++ b/src/main/java/org/gridsuite/voltageinit/server/service/parameters/FilterService.java @@ -30,6 +30,7 @@ import org.gridsuite.filter.utils.expertfilter.FieldType; import org.gridsuite.filter.utils.expertfilter.OperatorType; import org.gridsuite.voltageinit.server.dto.parameters.FilterEquipments; +import org.gridsuite.voltageinit.server.error.VoltageInitBusinessErrorCode; import org.gridsuite.voltageinit.server.error.VoltageInitException; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.ParameterizedTypeReference; @@ -133,7 +134,7 @@ public void ensureFiltersExist(Map filterNamesByUuid) { .filter(filterId -> !validFilters.contains(filterId)) .toList(); if (!missingFilters.isEmpty()) { - throw new VoltageInitException(buildMissingFiltersMessage(missingFilters, filterNamesByUuid)); + throw new VoltageInitException(VoltageInitBusinessErrorCode.MISSING_FILTER, buildMissingFiltersMessage(missingFilters, filterNamesByUuid)); } } diff --git a/src/test/java/org/gridsuite/voltageinit/server/PropertyServerNameProviderTest.java b/src/test/java/org/gridsuite/voltageinit/server/PropertyServerNameProviderTest.java new file mode 100644 index 0000000..7bdff14 --- /dev/null +++ b/src/test/java/org/gridsuite/voltageinit/server/PropertyServerNameProviderTest.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.voltageinit.server; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Hugo Marcellin + */ +class PropertyServerNameProviderTest { + + @Test + void returnsProvidedName() { + PropertyServerNameProvider provider = new PropertyServerNameProvider("custom-server"); + assertThat(provider.serverName()).isEqualTo("custom-server"); + } +} \ No newline at end of file diff --git a/src/test/java/org/gridsuite/voltageinit/server/VoltageInitBusinessErrorCodeTest.java b/src/test/java/org/gridsuite/voltageinit/server/VoltageInitBusinessErrorCodeTest.java new file mode 100644 index 0000000..5d667fb --- /dev/null +++ b/src/test/java/org/gridsuite/voltageinit/server/VoltageInitBusinessErrorCodeTest.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.voltageinit.server; + +import org.gridsuite.voltageinit.server.error.VoltageInitBusinessErrorCode; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import static org.gridsuite.voltageinit.utils.assertions.Assertions.assertThat; + +/** + * @author Hugo Marcellin + */ +class VoltageInitBusinessErrorCodeTest { + @ParameterizedTest + @EnumSource(VoltageInitBusinessErrorCode.class) + void valueMatchesEnumName(VoltageInitBusinessErrorCode code) { + assertThat(code.value()).startsWith("voltageInit."); + } +} diff --git a/src/test/java/org/gridsuite/voltageinit/server/service/parameters/ParametersTest.java b/src/test/java/org/gridsuite/voltageinit/server/service/parameters/ParametersTest.java index 187c9df..e488a7e 100644 --- a/src/test/java/org/gridsuite/voltageinit/server/service/parameters/ParametersTest.java +++ b/src/test/java/org/gridsuite/voltageinit/server/service/parameters/ParametersTest.java @@ -27,6 +27,7 @@ import org.gridsuite.voltageinit.server.entities.parameters.FilterEquipmentsEmbeddable; import org.gridsuite.voltageinit.server.entities.parameters.VoltageInitParametersEntity; import org.gridsuite.voltageinit.server.entities.parameters.VoltageLimitEntity; +import org.gridsuite.voltageinit.server.error.VoltageInitBusinessErrorCode; import org.gridsuite.voltageinit.server.error.VoltageInitException; import org.gridsuite.voltageinit.server.service.VoltageInitRunContext; import org.gridsuite.voltageinit.server.util.EquipmentsSelectionType; @@ -211,7 +212,7 @@ void buildOpenReacParametersThrowsWhenFilterMissing() { .withResourceBundles("i18n.reports") .withMessageTemplate(COMPUTATION_TYPE).build()); - Mockito.doThrow(new VoltageInitException(FilterService.FILTERS_NOT_FOUND + " [" + FILTER_1 + "]")) + Mockito.doThrow(new VoltageInitException(VoltageInitBusinessErrorCode.MISSING_FILTER, FilterService.FILTERS_NOT_FOUND + " [" + FILTER_1 + "]")) .when(filterService) .ensureFiltersExist(Mockito.anyMap());