From 70a8040696c014fb153b728614b0867aece2e0aa Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Thu, 13 Nov 2025 17:08:00 +0100 Subject: [PATCH 01/28] Harmonize exceptions handling --- pom.xml | 2 +- .../ComputationBusinessErrorCode.java | 26 ++++++++++ .../computation/ComputationException.java | 49 ++++++++----------- .../computation/utils/FilterUtils.java | 4 +- 4 files changed, 50 insertions(+), 31 deletions(-) create mode 100644 src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java diff --git a/pom.xml b/pom.xml index e91cd0d..a5e3e02 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,7 @@ 2.25.0 - 1.28.1 + 1.30.0 1.6.0 diff --git a/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java b/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java new file mode 100644 index 0000000..0a19390 --- /dev/null +++ b/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java @@ -0,0 +1,26 @@ +package org.gridsuite.computation; + +import com.powsybl.ws.commons.error.BusinessErrorCode; + +public enum ComputationBusinessErrorCode implements BusinessErrorCode { + RESULT_NOT_FOUND("computation.resultNotFound"), + INVALID_FILTER_FORMAT("computation.invalidFilterFormat"), + INVALID_SORT_FORMAT("computation.invalidSortFormat"), + INVALID_FILTER("computation.invalidFilter"), + NETWORK_NOT_FOUND("computation.networkNotFound"), + PARAMETERS_NOT_FOUND("computation.parametersNotFound"), + FILE_EXPORT_ERROR("computation.fileExportError"), + EVALUATE_FILTER_FAILED("computation.evaluateFilterFailed"), + LIMIT_REDUCTION_CONFIG_ERROR("computation.limitReductionConfigError"), + SPECIFIC("computation.specific"),; + + private final String code; + + ComputationBusinessErrorCode(String code) { + this.code = code; + } + + public String value() { + return code; + } +} diff --git a/src/main/java/org/gridsuite/computation/ComputationException.java b/src/main/java/org/gridsuite/computation/ComputationException.java index c19157f..12140ad 100644 --- a/src/main/java/org/gridsuite/computation/ComputationException.java +++ b/src/main/java/org/gridsuite/computation/ComputationException.java @@ -6,7 +6,10 @@ */ package org.gridsuite.computation; +import com.powsybl.ws.commons.error.AbstractBusinessException; +import com.powsybl.ws.commons.error.BusinessErrorCode; import lombok.Getter; +import lombok.NonNull; import java.util.Objects; @@ -14,50 +17,38 @@ * @author Anis Touri */ @Getter -public class ComputationException extends RuntimeException { - public enum Type { - RESULT_NOT_FOUND("Result not found."), - INVALID_FILTER_FORMAT("The filter format is invalid."), - INVALID_SORT_FORMAT("The sort format is invalid"), - INVALID_FILTER("Invalid filter"), - NETWORK_NOT_FOUND("Network not found"), - PARAMETERS_NOT_FOUND("Computation parameters not found"), - FILE_EXPORT_ERROR("Error exporting the file"), - EVALUATE_FILTER_FAILED("Error evaluating the file"), - LIMIT_REDUCTION_CONFIG_ERROR("Error int the configuration of the limit reduction"), - SPECIFIC("Unknown error during the computation"); - - private final String defaultMessage; - - Type(String defaultMessage) { - this.defaultMessage = defaultMessage; - } - } +public class ComputationException extends AbstractBusinessException { - private final Type exceptionType; + protected final BusinessErrorCode errorCode; - public ComputationException(Type exceptionType) { - super(Objects.requireNonNull(exceptionType.defaultMessage)); - this.exceptionType = Objects.requireNonNull(exceptionType); + public ComputationException(ComputationBusinessErrorCode exceptionType) { + super(Objects.requireNonNull(exceptionType.value())); + this.errorCode = Objects.requireNonNull(exceptionType); } public ComputationException(String message) { super(message); - this.exceptionType = Type.SPECIFIC; + this.errorCode = ComputationBusinessErrorCode.SPECIFIC; } public ComputationException(String message, Throwable cause) { super(message, cause); - this.exceptionType = Type.SPECIFIC; + this.errorCode = ComputationBusinessErrorCode.SPECIFIC; + } + + @NonNull + @Override + public BusinessErrorCode getBusinessErrorCode() { + return errorCode; } - public ComputationException(Type exceptionType, String message) { + public ComputationException(BusinessErrorCode exceptionType, String message) { super(message); - this.exceptionType = Objects.requireNonNull(exceptionType); + this.errorCode = Objects.requireNonNull(exceptionType); } - public ComputationException(Type exceptionType, String message, Throwable cause) { + public ComputationException(BusinessErrorCode exceptionType, String message, Throwable cause) { super(message, cause); - this.exceptionType = Objects.requireNonNull(exceptionType); + this.errorCode = Objects.requireNonNull(exceptionType); } } diff --git a/src/main/java/org/gridsuite/computation/utils/FilterUtils.java b/src/main/java/org/gridsuite/computation/utils/FilterUtils.java index b503df5..7906b14 100644 --- a/src/main/java/org/gridsuite/computation/utils/FilterUtils.java +++ b/src/main/java/org/gridsuite/computation/utils/FilterUtils.java @@ -16,6 +16,8 @@ import java.util.List; +import static org.gridsuite.computation.ComputationBusinessErrorCode.INVALID_FILTER_FORMAT; + /** * @author maissa Souissi */ @@ -32,7 +34,7 @@ private static T fromStringToDTO(String jsonString, ObjectMapper objectMappe try { return objectMapper.readValue(jsonString, typeReference); } catch (JsonProcessingException e) { - throw new ComputationException(ComputationException.Type.INVALID_FILTER_FORMAT); + throw new ComputationException(INVALID_FILTER_FORMAT); } } From 3a92f645c7119f27e8b56c66b91d0ba26b3eb713 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Thu, 13 Nov 2025 17:09:58 +0100 Subject: [PATCH 02/28] Add licence --- .../gridsuite/computation/ComputationBusinessErrorCode.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java b/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java index 0a19390..cb78a28 100644 --- a/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java +++ b/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java @@ -1,3 +1,9 @@ +/** + * 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.computation; import com.powsybl.ws.commons.error.BusinessErrorCode; From b48fa1f1f4a0f27db47e353440b9364cfd583726 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Thu, 13 Nov 2025 17:30:51 +0100 Subject: [PATCH 03/28] Add ComputationBusinessErrorCodeTest --- .../ComputationBusinessErrorCodeTest.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/test/java/org/gridsuite/computation/ComputationBusinessErrorCodeTest.java diff --git a/src/test/java/org/gridsuite/computation/ComputationBusinessErrorCodeTest.java b/src/test/java/org/gridsuite/computation/ComputationBusinessErrorCodeTest.java new file mode 100644 index 0000000..029555c --- /dev/null +++ b/src/test/java/org/gridsuite/computation/ComputationBusinessErrorCodeTest.java @@ -0,0 +1,20 @@ +/** + * 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.computation; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +public class ComputationBusinessErrorCodeTest { + @ParameterizedTest + @EnumSource(ComputationBusinessErrorCode.class) + void valueMatchesEnumName(ComputationBusinessErrorCode code) { + assertThat(code.value()).startsWith("computation."); + } +} From 42bee490d7ef60086f8c79bc77137e05d2ccf06c Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Thu, 13 Nov 2025 17:32:54 +0100 Subject: [PATCH 04/28] Unused constructor --- .../java/org/gridsuite/computation/ComputationException.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/org/gridsuite/computation/ComputationException.java b/src/main/java/org/gridsuite/computation/ComputationException.java index 12140ad..4c97593 100644 --- a/src/main/java/org/gridsuite/computation/ComputationException.java +++ b/src/main/java/org/gridsuite/computation/ComputationException.java @@ -46,9 +46,4 @@ public ComputationException(BusinessErrorCode exceptionType, String message) { super(message); this.errorCode = Objects.requireNonNull(exceptionType); } - - public ComputationException(BusinessErrorCode exceptionType, String message, Throwable cause) { - super(message, cause); - this.errorCode = Objects.requireNonNull(exceptionType); - } } From 344666fcbb6a85653229e064d7647d5cf99847ec Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Thu, 13 Nov 2025 17:40:53 +0100 Subject: [PATCH 05/28] Increase coverage --- .../org/gridsuite/computation/ComputationException.java | 7 +------ .../java/org/gridsuite/computation/utils/FilterUtils.java | 2 +- .../gridsuite/computation/ComputationExceptionTest.java | 8 ++++++++ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/gridsuite/computation/ComputationException.java b/src/main/java/org/gridsuite/computation/ComputationException.java index 4c97593..d7ea613 100644 --- a/src/main/java/org/gridsuite/computation/ComputationException.java +++ b/src/main/java/org/gridsuite/computation/ComputationException.java @@ -19,12 +19,7 @@ @Getter public class ComputationException extends AbstractBusinessException { - protected final BusinessErrorCode errorCode; - - public ComputationException(ComputationBusinessErrorCode exceptionType) { - super(Objects.requireNonNull(exceptionType.value())); - this.errorCode = Objects.requireNonNull(exceptionType); - } + private final BusinessErrorCode errorCode; public ComputationException(String message) { super(message); diff --git a/src/main/java/org/gridsuite/computation/utils/FilterUtils.java b/src/main/java/org/gridsuite/computation/utils/FilterUtils.java index 7906b14..300cd60 100644 --- a/src/main/java/org/gridsuite/computation/utils/FilterUtils.java +++ b/src/main/java/org/gridsuite/computation/utils/FilterUtils.java @@ -34,7 +34,7 @@ private static T fromStringToDTO(String jsonString, ObjectMapper objectMappe try { return objectMapper.readValue(jsonString, typeReference); } catch (JsonProcessingException e) { - throw new ComputationException(INVALID_FILTER_FORMAT); + throw new ComputationException(INVALID_FILTER_FORMAT, e.getMessage()); } } diff --git a/src/test/java/org/gridsuite/computation/ComputationExceptionTest.java b/src/test/java/org/gridsuite/computation/ComputationExceptionTest.java index fb9b670..7c0d99e 100644 --- a/src/test/java/org/gridsuite/computation/ComputationExceptionTest.java +++ b/src/test/java/org/gridsuite/computation/ComputationExceptionTest.java @@ -19,6 +19,7 @@ class ComputationExceptionTest { void testMessageConstructor() { var e = new ComputationException("test"); assertEquals("test", e.getMessage()); + assertEquals(ComputationBusinessErrorCode.SPECIFIC, e.getBusinessErrorCode()); } @Test @@ -28,4 +29,11 @@ void testMessageAndThrowableConstructor() { assertEquals("test", e.getMessage()); assertEquals(cause, e.getCause()); } + + @Test + void testBussinessErrorCodeConstructor() { + var e = new ComputationException(ComputationBusinessErrorCode.PARAMETERS_NOT_FOUND, "test"); + assertEquals("test", e.getMessage()); + assertEquals(ComputationBusinessErrorCode.PARAMETERS_NOT_FOUND, e.getBusinessErrorCode()); + } } From 205de9493f335777f58c51826fa9e050b8ddc0fc Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Thu, 13 Nov 2025 17:44:34 +0100 Subject: [PATCH 06/28] Sonar issue --- .../gridsuite/computation/ComputationBusinessErrorCodeTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/gridsuite/computation/ComputationBusinessErrorCodeTest.java b/src/test/java/org/gridsuite/computation/ComputationBusinessErrorCodeTest.java index 029555c..7fb2d3c 100644 --- a/src/test/java/org/gridsuite/computation/ComputationBusinessErrorCodeTest.java +++ b/src/test/java/org/gridsuite/computation/ComputationBusinessErrorCodeTest.java @@ -11,7 +11,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -public class ComputationBusinessErrorCodeTest { +class ComputationBusinessErrorCodeTest { @ParameterizedTest @EnumSource(ComputationBusinessErrorCode.class) void valueMatchesEnumName(ComputationBusinessErrorCode code) { From 66ec52f02dda964999039cc4c41245ca1278bae7 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Thu, 13 Nov 2025 17:45:39 +0100 Subject: [PATCH 07/28] Sonar issue --- .../java/org/gridsuite/computation/ComputationException.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/gridsuite/computation/ComputationException.java b/src/main/java/org/gridsuite/computation/ComputationException.java index d7ea613..b716388 100644 --- a/src/main/java/org/gridsuite/computation/ComputationException.java +++ b/src/main/java/org/gridsuite/computation/ComputationException.java @@ -19,7 +19,7 @@ @Getter public class ComputationException extends AbstractBusinessException { - private final BusinessErrorCode errorCode; + private final ComputationBusinessErrorCode errorCode; public ComputationException(String message) { super(message); @@ -37,7 +37,7 @@ public BusinessErrorCode getBusinessErrorCode() { return errorCode; } - public ComputationException(BusinessErrorCode exceptionType, String message) { + public ComputationException(ComputationBusinessErrorCode exceptionType, String message) { super(message); this.errorCode = Objects.requireNonNull(exceptionType); } From 9007608f2e91614045224ae072bbedb83dece6a2 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Thu, 13 Nov 2025 17:47:27 +0100 Subject: [PATCH 08/28] Typo --- .../java/org/gridsuite/computation/ComputationException.java | 4 ++-- .../org/gridsuite/computation/ComputationExceptionTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/gridsuite/computation/ComputationException.java b/src/main/java/org/gridsuite/computation/ComputationException.java index b716388..6f237fc 100644 --- a/src/main/java/org/gridsuite/computation/ComputationException.java +++ b/src/main/java/org/gridsuite/computation/ComputationException.java @@ -37,8 +37,8 @@ public BusinessErrorCode getBusinessErrorCode() { return errorCode; } - public ComputationException(ComputationBusinessErrorCode exceptionType, String message) { + public ComputationException(ComputationBusinessErrorCode errorCode, String message) { super(message); - this.errorCode = Objects.requireNonNull(exceptionType); + this.errorCode = Objects.requireNonNull(errorCode); } } diff --git a/src/test/java/org/gridsuite/computation/ComputationExceptionTest.java b/src/test/java/org/gridsuite/computation/ComputationExceptionTest.java index 7c0d99e..6528b9a 100644 --- a/src/test/java/org/gridsuite/computation/ComputationExceptionTest.java +++ b/src/test/java/org/gridsuite/computation/ComputationExceptionTest.java @@ -31,7 +31,7 @@ void testMessageAndThrowableConstructor() { } @Test - void testBussinessErrorCodeConstructor() { + void testBusinessErrorCodeConstructor() { var e = new ComputationException(ComputationBusinessErrorCode.PARAMETERS_NOT_FOUND, "test"); assertEquals("test", e.getMessage()); assertEquals(ComputationBusinessErrorCode.PARAMETERS_NOT_FOUND, e.getBusinessErrorCode()); From 4ea7fa7b92ee38126d8c5ca75910eded13e1daa2 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Fri, 14 Nov 2025 11:47:31 +0100 Subject: [PATCH 09/28] Fix typing --- .../java/org/gridsuite/computation/ComputationException.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/gridsuite/computation/ComputationException.java b/src/main/java/org/gridsuite/computation/ComputationException.java index 6f237fc..a822e86 100644 --- a/src/main/java/org/gridsuite/computation/ComputationException.java +++ b/src/main/java/org/gridsuite/computation/ComputationException.java @@ -33,7 +33,7 @@ public ComputationException(String message, Throwable cause) { @NonNull @Override - public BusinessErrorCode getBusinessErrorCode() { + public ComputationBusinessErrorCode getBusinessErrorCode() { return errorCode; } From 1c0c5e434291d7173bd78e37e88e91dcadd503d7 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Fri, 14 Nov 2025 14:34:06 +0100 Subject: [PATCH 10/28] Replace BusinessErrorCode --- .../java/org/gridsuite/computation/ComputationException.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/gridsuite/computation/ComputationException.java b/src/main/java/org/gridsuite/computation/ComputationException.java index a822e86..07675bc 100644 --- a/src/main/java/org/gridsuite/computation/ComputationException.java +++ b/src/main/java/org/gridsuite/computation/ComputationException.java @@ -7,7 +7,6 @@ package org.gridsuite.computation; import com.powsybl.ws.commons.error.AbstractBusinessException; -import com.powsybl.ws.commons.error.BusinessErrorCode; import lombok.Getter; import lombok.NonNull; From 57c8cd1f8bde392879480ff46a49aede86c80a86 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Tue, 18 Nov 2025 10:53:50 +0100 Subject: [PATCH 11/28] Mutualize INVALID_EXPORT_PARAMS --- .../gridsuite/computation/ComputationBusinessErrorCode.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java b/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java index cb78a28..4dfd549 100644 --- a/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java +++ b/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java @@ -13,12 +13,13 @@ public enum ComputationBusinessErrorCode implements BusinessErrorCode { INVALID_FILTER_FORMAT("computation.invalidFilterFormat"), INVALID_SORT_FORMAT("computation.invalidSortFormat"), INVALID_FILTER("computation.invalidFilter"), + INVALID_EXPORT_PARAMS("computation.invalidExportParams"), NETWORK_NOT_FOUND("computation.networkNotFound"), PARAMETERS_NOT_FOUND("computation.parametersNotFound"), FILE_EXPORT_ERROR("computation.fileExportError"), EVALUATE_FILTER_FAILED("computation.evaluateFilterFailed"), LIMIT_REDUCTION_CONFIG_ERROR("computation.limitReductionConfigError"), - SPECIFIC("computation.specific"),; + SPECIFIC("computation.specific"); private final String code; From da807d72dd2f9f292b54486f8bbbd58533eea785 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Tue, 18 Nov 2025 14:54:47 +0100 Subject: [PATCH 12/28] Mutualize invalid parameter error code --- .../org/gridsuite/computation/ComputationBusinessErrorCode.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java b/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java index 4dfd549..a6b686c 100644 --- a/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java +++ b/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java @@ -16,6 +16,7 @@ public enum ComputationBusinessErrorCode implements BusinessErrorCode { INVALID_EXPORT_PARAMS("computation.invalidExportParams"), NETWORK_NOT_FOUND("computation.networkNotFound"), PARAMETERS_NOT_FOUND("computation.parametersNotFound"), + INVALID_PARAMETERS("computation.invalidParameters"), FILE_EXPORT_ERROR("computation.fileExportError"), EVALUATE_FILTER_FAILED("computation.evaluateFilterFailed"), LIMIT_REDUCTION_CONFIG_ERROR("computation.limitReductionConfigError"), From cc474a05dca69684ac00bd7d1d4f4924226af69c Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Tue, 18 Nov 2025 17:50:01 +0100 Subject: [PATCH 13/28] Remove unused and technical errors --- .../ComputationBusinessErrorCode.java | 10 ++-------- .../computation/ComputationException.java | 15 +++++---------- .../service/AbstractWorkerService.java | 3 ++- .../computation/ComputationExceptionTest.java | 16 ++++++---------- 4 files changed, 15 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java b/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java index a6b686c..43095a4 100644 --- a/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java +++ b/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java @@ -10,17 +10,11 @@ public enum ComputationBusinessErrorCode implements BusinessErrorCode { RESULT_NOT_FOUND("computation.resultNotFound"), - INVALID_FILTER_FORMAT("computation.invalidFilterFormat"), + PARAMETERS_NOT_FOUND("computation.parametersNotFound"), INVALID_SORT_FORMAT("computation.invalidSortFormat"), - INVALID_FILTER("computation.invalidFilter"), INVALID_EXPORT_PARAMS("computation.invalidExportParams"), - NETWORK_NOT_FOUND("computation.networkNotFound"), - PARAMETERS_NOT_FOUND("computation.parametersNotFound"), - INVALID_PARAMETERS("computation.invalidParameters"), - FILE_EXPORT_ERROR("computation.fileExportError"), - EVALUATE_FILTER_FAILED("computation.evaluateFilterFailed"), LIMIT_REDUCTION_CONFIG_ERROR("computation.limitReductionConfigError"), - SPECIFIC("computation.specific"); + RUNNER_ERROR("computation.runnerError"); private final String code; diff --git a/src/main/java/org/gridsuite/computation/ComputationException.java b/src/main/java/org/gridsuite/computation/ComputationException.java index 07675bc..729bd40 100644 --- a/src/main/java/org/gridsuite/computation/ComputationException.java +++ b/src/main/java/org/gridsuite/computation/ComputationException.java @@ -20,22 +20,17 @@ public class ComputationException extends AbstractBusinessException { private final ComputationBusinessErrorCode errorCode; - public ComputationException(String message) { - super(message); - this.errorCode = ComputationBusinessErrorCode.SPECIFIC; - } - - public ComputationException(String message, Throwable cause) { - super(message, cause); - this.errorCode = ComputationBusinessErrorCode.SPECIFIC; - } - @NonNull @Override public ComputationBusinessErrorCode getBusinessErrorCode() { return errorCode; } + public ComputationException(ComputationBusinessErrorCode errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = errorCode; + } + public ComputationException(ComputationBusinessErrorCode errorCode, String message) { super(message); this.errorCode = Objects.requireNonNull(errorCode); diff --git a/src/main/java/org/gridsuite/computation/service/AbstractWorkerService.java b/src/main/java/org/gridsuite/computation/service/AbstractWorkerService.java index 77d9140..58e5492 100644 --- a/src/main/java/org/gridsuite/computation/service/AbstractWorkerService.java +++ b/src/main/java/org/gridsuite/computation/service/AbstractWorkerService.java @@ -16,6 +16,7 @@ import com.powsybl.network.store.client.PreloadingStrategy; import com.powsybl.ws.commons.ZipUtils; import org.apache.commons.lang3.StringUtils; +import org.gridsuite.computation.ComputationBusinessErrorCode; import org.gridsuite.computation.ComputationException; import org.gridsuite.computation.s3.ComputationS3Service; import org.slf4j.Logger; @@ -180,7 +181,7 @@ public Consumer> consumeRun() { } catch (Exception e) { resultService.delete(resultContext.getResultUuid()); this.handleNonCancellationException(resultContext, e, rootReporter); - throw new ComputationException(String.format("%s: %s", NotificationService.getFailedMessage(getComputationType()), e.getMessage()), e.getCause()); + throw new ComputationException(ComputationBusinessErrorCode.RUNNER_ERROR, String.format("%s: %s", NotificationService.getFailedMessage(getComputationType()), e.getMessage()), e.getCause()); } finally { if (Boolean.TRUE.equals(resultContext.getRunContext().getDebug())) { processDebug(resultContext); diff --git a/src/test/java/org/gridsuite/computation/ComputationExceptionTest.java b/src/test/java/org/gridsuite/computation/ComputationExceptionTest.java index 6528b9a..db062b2 100644 --- a/src/test/java/org/gridsuite/computation/ComputationExceptionTest.java +++ b/src/test/java/org/gridsuite/computation/ComputationExceptionTest.java @@ -8,6 +8,8 @@ import org.junit.jupiter.api.Test; +import static org.gridsuite.computation.ComputationBusinessErrorCode.PARAMETERS_NOT_FOUND; +import static org.gridsuite.computation.ComputationBusinessErrorCode.RUNNER_ERROR; import static org.junit.jupiter.api.Assertions.*; /** @@ -15,25 +17,19 @@ */ class ComputationExceptionTest { - @Test - void testMessageConstructor() { - var e = new ComputationException("test"); - assertEquals("test", e.getMessage()); - assertEquals(ComputationBusinessErrorCode.SPECIFIC, e.getBusinessErrorCode()); - } - @Test void testMessageAndThrowableConstructor() { var cause = new RuntimeException("test"); - var e = new ComputationException("test", cause); + var e = new ComputationException(RUNNER_ERROR, "test", cause); + assertEquals(RUNNER_ERROR, e.getBusinessErrorCode()); assertEquals("test", e.getMessage()); assertEquals(cause, e.getCause()); } @Test void testBusinessErrorCodeConstructor() { - var e = new ComputationException(ComputationBusinessErrorCode.PARAMETERS_NOT_FOUND, "test"); + var e = new ComputationException(PARAMETERS_NOT_FOUND, "test"); assertEquals("test", e.getMessage()); - assertEquals(ComputationBusinessErrorCode.PARAMETERS_NOT_FOUND, e.getBusinessErrorCode()); + assertEquals(PARAMETERS_NOT_FOUND, e.getBusinessErrorCode()); } } From a96c08f5302f6c0b8bc6113efa1fcf0bc3fde14d Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Tue, 18 Nov 2025 17:50:35 +0100 Subject: [PATCH 14/28] technical error --- .../java/org/gridsuite/computation/utils/FilterUtils.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/gridsuite/computation/utils/FilterUtils.java b/src/main/java/org/gridsuite/computation/utils/FilterUtils.java index 300cd60..f250a80 100644 --- a/src/main/java/org/gridsuite/computation/utils/FilterUtils.java +++ b/src/main/java/org/gridsuite/computation/utils/FilterUtils.java @@ -10,13 +10,12 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.lang3.StringUtils; -import org.gridsuite.computation.ComputationException; import org.gridsuite.computation.dto.GlobalFilter; import org.gridsuite.computation.dto.ResourceFilterDTO; +import java.io.UncheckedIOException; import java.util.List; -import static org.gridsuite.computation.ComputationBusinessErrorCode.INVALID_FILTER_FORMAT; /** * @author maissa Souissi @@ -34,7 +33,7 @@ private static T fromStringToDTO(String jsonString, ObjectMapper objectMappe try { return objectMapper.readValue(jsonString, typeReference); } catch (JsonProcessingException e) { - throw new ComputationException(INVALID_FILTER_FORMAT, e.getMessage()); + throw new UncheckedIOException(e); } } From 42d3d2ffb4c03188774ed8a46e099125f9de2e1b Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Tue, 18 Nov 2025 18:00:02 +0100 Subject: [PATCH 15/28] checkstyle --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e800828..0a8f96e 100644 --- a/pom.xml +++ b/pom.xml @@ -44,8 +44,8 @@ 2.27.0 1.13.0 - 2.2 + 2.2 3.3.0 gridsuite From ce5cc103e9479dddf0ba1a7a0337e8a39ae01005 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Wed, 19 Nov 2025 11:52:11 +0100 Subject: [PATCH 16/28] Fix test --- .../java/org/gridsuite/computation/utils/FilterUtilsTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/gridsuite/computation/utils/FilterUtilsTest.java b/src/test/java/org/gridsuite/computation/utils/FilterUtilsTest.java index a392c7a..7f88c68 100644 --- a/src/test/java/org/gridsuite/computation/utils/FilterUtilsTest.java +++ b/src/test/java/org/gridsuite/computation/utils/FilterUtilsTest.java @@ -15,6 +15,7 @@ import org.gridsuite.computation.dto.ResourceFilterDTO; import org.junit.jupiter.api.Test; +import java.io.UncheckedIOException; import java.util.List; import java.util.Map; import java.util.UUID; @@ -73,7 +74,7 @@ void testFromStringGlobalFiltersToDTO() throws Exception { @Test void testInvalidFilterFormat() { - assertThrows(ComputationException.class, () -> FilterUtils.fromStringGlobalFiltersToDTO("titi", objectMapper), "The filter format is invalid."); + assertThrows(UncheckedIOException.class, () -> FilterUtils.fromStringGlobalFiltersToDTO("titi", objectMapper), "The filter format is invalid."); } @Test From ff253342adef151b091f8519d416b5516aa74dc8 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Wed, 19 Nov 2025 11:55:16 +0100 Subject: [PATCH 17/28] Checkstyle --- .../org/gridsuite/computation/utils/FilterUtilsTest.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/test/java/org/gridsuite/computation/utils/FilterUtilsTest.java b/src/test/java/org/gridsuite/computation/utils/FilterUtilsTest.java index 7f88c68..12a0e70 100644 --- a/src/test/java/org/gridsuite/computation/utils/FilterUtilsTest.java +++ b/src/test/java/org/gridsuite/computation/utils/FilterUtilsTest.java @@ -10,7 +10,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.powsybl.iidm.network.Country; import com.powsybl.security.LimitViolationType; -import org.gridsuite.computation.ComputationException; import org.gridsuite.computation.dto.GlobalFilter; import org.gridsuite.computation.dto.ResourceFilterDTO; import org.junit.jupiter.api.Test; @@ -20,11 +19,7 @@ import java.util.Map; import java.util.UUID; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; /** * @author Franck Lecuyer From 25c9daaf73babc4c951e1036285f2ac72ea52728 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Fri, 21 Nov 2025 17:37:44 +0100 Subject: [PATCH 18/28] Mutualize RestResponseEntityExceptionHandler --- .../ComputationBusinessErrorCode.java | 2 +- .../{ => error}/ComputationException.java | 2 +- .../RestResponseEntityExceptionHandler.java | 41 +++++++++++++++++++ .../service/AbstractWorkerService.java | 4 +- .../ComputationBusinessErrorCodeTest.java | 1 + .../computation/ComputationExceptionTest.java | 5 ++- .../computation/ComputationTest.java | 1 + 7 files changed, 50 insertions(+), 6 deletions(-) rename src/main/java/org/gridsuite/computation/{ => error}/ComputationBusinessErrorCode.java (95%) rename src/main/java/org/gridsuite/computation/{ => error}/ComputationException.java (96%) create mode 100644 src/main/java/org/gridsuite/computation/error/RestResponseEntityExceptionHandler.java diff --git a/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java b/src/main/java/org/gridsuite/computation/error/ComputationBusinessErrorCode.java similarity index 95% rename from src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java rename to src/main/java/org/gridsuite/computation/error/ComputationBusinessErrorCode.java index 43095a4..8345778 100644 --- a/src/main/java/org/gridsuite/computation/ComputationBusinessErrorCode.java +++ b/src/main/java/org/gridsuite/computation/error/ComputationBusinessErrorCode.java @@ -4,7 +4,7 @@ * 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.computation; +package org.gridsuite.computation.error; import com.powsybl.ws.commons.error.BusinessErrorCode; diff --git a/src/main/java/org/gridsuite/computation/ComputationException.java b/src/main/java/org/gridsuite/computation/error/ComputationException.java similarity index 96% rename from src/main/java/org/gridsuite/computation/ComputationException.java rename to src/main/java/org/gridsuite/computation/error/ComputationException.java index 729bd40..71e54ef 100644 --- a/src/main/java/org/gridsuite/computation/ComputationException.java +++ b/src/main/java/org/gridsuite/computation/error/ComputationException.java @@ -4,7 +4,7 @@ * 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.computation; +package org.gridsuite.computation.error; import com.powsybl.ws.commons.error.AbstractBusinessException; import lombok.Getter; diff --git a/src/main/java/org/gridsuite/computation/error/RestResponseEntityExceptionHandler.java b/src/main/java/org/gridsuite/computation/error/RestResponseEntityExceptionHandler.java new file mode 100644 index 0000000..2519701 --- /dev/null +++ b/src/main/java/org/gridsuite/computation/error/RestResponseEntityExceptionHandler.java @@ -0,0 +1,41 @@ +package org.gridsuite.computation.error; + +import com.powsybl.ws.commons.error.AbstractBaseRestExceptionHandler; +import com.powsybl.ws.commons.error.AbstractBusinessException; +import com.powsybl.ws.commons.error.BusinessErrorCode; +import com.powsybl.ws.commons.error.ServerNameProvider; +import lombok.NonNull; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ControllerAdvice; + +import static org.gridsuite.computation.error.ComputationBusinessErrorCode.INVALID_EXPORT_PARAMS; +import static org.gridsuite.computation.error.ComputationBusinessErrorCode.INVALID_SORT_FORMAT; +import static org.gridsuite.computation.error.ComputationBusinessErrorCode.PARAMETERS_NOT_FOUND; +import static org.gridsuite.computation.error.ComputationBusinessErrorCode.RESULT_NOT_FOUND; + +/** + * @author Hugo Marcellin + */ + +@ControllerAdvice +public class RestResponseEntityExceptionHandler extends AbstractBaseRestExceptionHandler { + + protected RestResponseEntityExceptionHandler(ServerNameProvider serverNameProvider) { + super(serverNameProvider); + } + + @Override + protected @NonNull BusinessErrorCode getBusinessCode(AbstractBusinessException e) { + return e.getBusinessErrorCode(); + } + + @Override + protected HttpStatus mapStatus(BusinessErrorCode businessErrorCode) { + return switch (businessErrorCode) { + case RESULT_NOT_FOUND, PARAMETERS_NOT_FOUND -> HttpStatus.NOT_FOUND; + case INVALID_SORT_FORMAT, + INVALID_EXPORT_PARAMS -> HttpStatus.BAD_REQUEST; + default -> HttpStatus.INTERNAL_SERVER_ERROR; + }; + } +} diff --git a/src/main/java/org/gridsuite/computation/service/AbstractWorkerService.java b/src/main/java/org/gridsuite/computation/service/AbstractWorkerService.java index 58e5492..2dfdddb 100644 --- a/src/main/java/org/gridsuite/computation/service/AbstractWorkerService.java +++ b/src/main/java/org/gridsuite/computation/service/AbstractWorkerService.java @@ -16,8 +16,8 @@ import com.powsybl.network.store.client.PreloadingStrategy; import com.powsybl.ws.commons.ZipUtils; import org.apache.commons.lang3.StringUtils; -import org.gridsuite.computation.ComputationBusinessErrorCode; -import org.gridsuite.computation.ComputationException; +import org.gridsuite.computation.error.ComputationBusinessErrorCode; +import org.gridsuite.computation.error.ComputationException; import org.gridsuite.computation.s3.ComputationS3Service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/test/java/org/gridsuite/computation/ComputationBusinessErrorCodeTest.java b/src/test/java/org/gridsuite/computation/ComputationBusinessErrorCodeTest.java index 7fb2d3c..796f73c 100644 --- a/src/test/java/org/gridsuite/computation/ComputationBusinessErrorCodeTest.java +++ b/src/test/java/org/gridsuite/computation/ComputationBusinessErrorCodeTest.java @@ -6,6 +6,7 @@ */ package org.gridsuite.computation; +import org.gridsuite.computation.error.ComputationBusinessErrorCode; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; diff --git a/src/test/java/org/gridsuite/computation/ComputationExceptionTest.java b/src/test/java/org/gridsuite/computation/ComputationExceptionTest.java index db062b2..75a2c37 100644 --- a/src/test/java/org/gridsuite/computation/ComputationExceptionTest.java +++ b/src/test/java/org/gridsuite/computation/ComputationExceptionTest.java @@ -6,10 +6,11 @@ */ package org.gridsuite.computation; +import org.gridsuite.computation.error.ComputationException; import org.junit.jupiter.api.Test; -import static org.gridsuite.computation.ComputationBusinessErrorCode.PARAMETERS_NOT_FOUND; -import static org.gridsuite.computation.ComputationBusinessErrorCode.RUNNER_ERROR; +import static org.gridsuite.computation.error.ComputationBusinessErrorCode.PARAMETERS_NOT_FOUND; +import static org.gridsuite.computation.error.ComputationBusinessErrorCode.RUNNER_ERROR; import static org.junit.jupiter.api.Assertions.*; /** diff --git a/src/test/java/org/gridsuite/computation/ComputationTest.java b/src/test/java/org/gridsuite/computation/ComputationTest.java index d3b110f..4719575 100644 --- a/src/test/java/org/gridsuite/computation/ComputationTest.java +++ b/src/test/java/org/gridsuite/computation/ComputationTest.java @@ -26,6 +26,7 @@ import lombok.extern.slf4j.Slf4j; import org.assertj.core.api.WithAssertions; import org.gridsuite.computation.dto.ReportInfos; +import org.gridsuite.computation.error.ComputationException; import org.gridsuite.computation.s3.ComputationS3Service; import org.gridsuite.computation.s3.S3InputStreamInfos; import org.gridsuite.computation.service.*; From a6b5300b3a5c904bf3c178edb3b56391415c85cc Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Mon, 24 Nov 2025 16:00:42 +0100 Subject: [PATCH 19/28] Increase coverage --- ...estResponseEntityExceptionHandlerTest.java | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 src/test/java/org/gridsuite/computation/RestResponseEntityExceptionHandlerTest.java diff --git a/src/test/java/org/gridsuite/computation/RestResponseEntityExceptionHandlerTest.java b/src/test/java/org/gridsuite/computation/RestResponseEntityExceptionHandlerTest.java new file mode 100644 index 0000000..0158381 --- /dev/null +++ b/src/test/java/org/gridsuite/computation/RestResponseEntityExceptionHandlerTest.java @@ -0,0 +1,94 @@ +package org.gridsuite.computation; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.powsybl.ws.commons.error.PowsyblWsProblemDetail; +import org.gridsuite.computation.error.ComputationException; +import org.gridsuite.computation.error.RestResponseEntityExceptionHandler; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.web.client.HttpClientErrorException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.gridsuite.computation.error.ComputationBusinessErrorCode.INVALID_SORT_FORMAT; +import static org.gridsuite.computation.error.ComputationBusinessErrorCode.RESULT_NOT_FOUND; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class RestResponseEntityExceptionHandlerTest { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper().registerModule(new JavaTimeModule()); + + private TestRestResponseEntityExceptionHandler handler; + + @BeforeEach + void setUp() { + handler = new TestRestResponseEntityExceptionHandler(); + } + + @Test + void mapsNotFoundBusinessErrorToStatus() { + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/results-endpoint/uuid"); + ComputationException exception = new ComputationException(RESULT_NOT_FOUND, "Result not found"); + ResponseEntity response = handler.invokeHandleDomainException(exception, request); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); + assertThat(response.getBody()).isNotNull(); + assertEquals("computation.resultNotFound", response.getBody().getBusinessErrorCode()); + } + + @Test + void mapsBadRequestBusinessErrorToStatus() { + MockHttpServletRequest request = new MockHttpServletRequest("POST", "/results-endpoint/uuid"); + ComputationException exception = new ComputationException(INVALID_SORT_FORMAT, "Invalid sort format"); + ResponseEntity response = handler.invokeHandleDomainException(exception, request); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); + assertThat(response.getBody()).isNotNull(); + assertEquals("computation.invalidSortFormat", response.getBody().getBusinessErrorCode()); + } + + @Test + void propagatesRemoteErrorDetails() throws JsonProcessingException { + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/computations/remote"); + PowsyblWsProblemDetail remote = PowsyblWsProblemDetail.builder(HttpStatus.INTERNAL_SERVER_ERROR) + .server("computation") + .businessErrorCode("computation.remoteError") + .detail("Computation failure") + .path("/computation") + .build(); + + HttpClientErrorException exception = HttpClientErrorException.create( + HttpStatus.INTERNAL_SERVER_ERROR, + "error", + HttpHeaders.EMPTY, + OBJECT_MAPPER.writeValueAsBytes(remote), + null + ); + + ResponseEntity response = handler.invokeHandleRemoteException(exception, request); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); + assertThat(response.getBody()).isNotNull(); + assertEquals("computation.remoteError", response.getBody().getBusinessErrorCode()); + assertThat(response.getBody().getChain()).hasSize(1); + } + + private static final class TestRestResponseEntityExceptionHandler extends RestResponseEntityExceptionHandler { + private TestRestResponseEntityExceptionHandler() { + super(() -> "computation-server"); + } + + ResponseEntity invokeHandleDomainException(ComputationException exception, MockHttpServletRequest request) { + return super.handleDomainException(exception, request); + } + + ResponseEntity invokeHandleRemoteException(HttpClientErrorException exception, MockHttpServletRequest request) { + return super.handleRemoteException(exception, request); + } + } +} \ No newline at end of file From 63deea0a5b617b60ef34e8efc6943bb50be13280 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Mon, 24 Nov 2025 16:01:35 +0100 Subject: [PATCH 20/28] Missing licence --- .../error/RestResponseEntityExceptionHandler.java | 6 ++++++ .../computation/RestResponseEntityExceptionHandlerTest.java | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/main/java/org/gridsuite/computation/error/RestResponseEntityExceptionHandler.java b/src/main/java/org/gridsuite/computation/error/RestResponseEntityExceptionHandler.java index 2519701..41c880b 100644 --- a/src/main/java/org/gridsuite/computation/error/RestResponseEntityExceptionHandler.java +++ b/src/main/java/org/gridsuite/computation/error/RestResponseEntityExceptionHandler.java @@ -1,3 +1,9 @@ +/** + * 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.computation.error; import com.powsybl.ws.commons.error.AbstractBaseRestExceptionHandler; diff --git a/src/test/java/org/gridsuite/computation/RestResponseEntityExceptionHandlerTest.java b/src/test/java/org/gridsuite/computation/RestResponseEntityExceptionHandlerTest.java index 0158381..d88b769 100644 --- a/src/test/java/org/gridsuite/computation/RestResponseEntityExceptionHandlerTest.java +++ b/src/test/java/org/gridsuite/computation/RestResponseEntityExceptionHandlerTest.java @@ -1,3 +1,9 @@ +/** + * 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.computation; import com.fasterxml.jackson.core.JsonProcessingException; From 0de2f97de8aae13d65d41dfabb236f1877c199b8 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Mon, 24 Nov 2025 16:02:54 +0100 Subject: [PATCH 21/28] Checkstyle --- .../computation/RestResponseEntityExceptionHandlerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/gridsuite/computation/RestResponseEntityExceptionHandlerTest.java b/src/test/java/org/gridsuite/computation/RestResponseEntityExceptionHandlerTest.java index d88b769..008d346 100644 --- a/src/test/java/org/gridsuite/computation/RestResponseEntityExceptionHandlerTest.java +++ b/src/test/java/org/gridsuite/computation/RestResponseEntityExceptionHandlerTest.java @@ -97,4 +97,4 @@ ResponseEntity invokeHandleRemoteException(HttpClientErr return super.handleRemoteException(exception, request); } } -} \ No newline at end of file +} From 3c30e62b51b7d975ed6885a241494bfbfe1b281f Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Wed, 26 Nov 2025 15:46:22 +0100 Subject: [PATCH 22/28] Add abstraction to combine mapping of computation error codes and specific codes in a common exception handler --- ...onRestResponseEntityExceptionHandler.java} | 7 ++-- ...ionRestResponseEntityExceptionHandler.java | 36 +++++++++++++++++ ...estResponseEntityExceptionHandlerTest.java | 35 ++++++++++------ .../error/utils/SpecificErrorCode.java | 24 +++++++++++ .../error/utils/SpecificException.java | 30 ++++++++++++++ ...estRestResponseEntityExceptionHandler.java | 31 ++++++++++++++ .../TestTypedRestResponseEntityException.java | 40 +++++++++++++++++++ 7 files changed, 186 insertions(+), 17 deletions(-) rename src/main/java/org/gridsuite/computation/error/{RestResponseEntityExceptionHandler.java => ComputationRestResponseEntityExceptionHandler.java} (82%) create mode 100644 src/main/java/org/gridsuite/computation/error/TypedComputationRestResponseEntityExceptionHandler.java rename src/test/java/org/gridsuite/computation/{ => error}/RestResponseEntityExceptionHandlerTest.java (74%) create mode 100644 src/test/java/org/gridsuite/computation/error/utils/SpecificErrorCode.java create mode 100644 src/test/java/org/gridsuite/computation/error/utils/SpecificException.java create mode 100644 src/test/java/org/gridsuite/computation/error/utils/TestRestResponseEntityExceptionHandler.java create mode 100644 src/test/java/org/gridsuite/computation/error/utils/TestTypedRestResponseEntityException.java diff --git a/src/main/java/org/gridsuite/computation/error/RestResponseEntityExceptionHandler.java b/src/main/java/org/gridsuite/computation/error/ComputationRestResponseEntityExceptionHandler.java similarity index 82% rename from src/main/java/org/gridsuite/computation/error/RestResponseEntityExceptionHandler.java rename to src/main/java/org/gridsuite/computation/error/ComputationRestResponseEntityExceptionHandler.java index 41c880b..89064ab 100644 --- a/src/main/java/org/gridsuite/computation/error/RestResponseEntityExceptionHandler.java +++ b/src/main/java/org/gridsuite/computation/error/ComputationRestResponseEntityExceptionHandler.java @@ -24,9 +24,9 @@ */ @ControllerAdvice -public class RestResponseEntityExceptionHandler extends AbstractBaseRestExceptionHandler { +public class ComputationRestResponseEntityExceptionHandler extends AbstractBaseRestExceptionHandler { - protected RestResponseEntityExceptionHandler(ServerNameProvider serverNameProvider) { + protected ComputationRestResponseEntityExceptionHandler(ServerNameProvider serverNameProvider) { super(serverNameProvider); } @@ -39,8 +39,7 @@ protected RestResponseEntityExceptionHandler(ServerNameProvider serverNameProvid protected HttpStatus mapStatus(BusinessErrorCode businessErrorCode) { return switch (businessErrorCode) { case RESULT_NOT_FOUND, PARAMETERS_NOT_FOUND -> HttpStatus.NOT_FOUND; - case INVALID_SORT_FORMAT, - INVALID_EXPORT_PARAMS -> HttpStatus.BAD_REQUEST; + case INVALID_SORT_FORMAT, INVALID_EXPORT_PARAMS -> HttpStatus.BAD_REQUEST; default -> HttpStatus.INTERNAL_SERVER_ERROR; }; } diff --git a/src/main/java/org/gridsuite/computation/error/TypedComputationRestResponseEntityExceptionHandler.java b/src/main/java/org/gridsuite/computation/error/TypedComputationRestResponseEntityExceptionHandler.java new file mode 100644 index 0000000..896b0da --- /dev/null +++ b/src/main/java/org/gridsuite/computation/error/TypedComputationRestResponseEntityExceptionHandler.java @@ -0,0 +1,36 @@ +/** + * 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.computation.error; + +import com.powsybl.ws.commons.error.BusinessErrorCode; +import com.powsybl.ws.commons.error.ServerNameProvider; +import org.springframework.http.HttpStatus; + +/** + * @author Hugo Marcellin + */ + +public abstract class TypedComputationRestResponseEntityExceptionHandler extends ComputationRestResponseEntityExceptionHandler { + private final Class specificComputationBusinessErrorCode; + + protected TypedComputationRestResponseEntityExceptionHandler(ServerNameProvider serverNameProvider, Class specificComputationBusinessErrorCode) { + super(serverNameProvider); + this.specificComputationBusinessErrorCode = specificComputationBusinessErrorCode; + } + + @Override + protected HttpStatus mapStatus(BusinessErrorCode businessErrorCode) { + if (businessErrorCode instanceof ComputationBusinessErrorCode computationCode) { + return super.mapStatus(computationCode); + } else if (specificComputationBusinessErrorCode.isInstance(businessErrorCode)) { + return mapSpecificStatus(specificComputationBusinessErrorCode.cast(businessErrorCode)); + } + return HttpStatus.INTERNAL_SERVER_ERROR; + } + + protected abstract HttpStatus mapSpecificStatus(C code); +} diff --git a/src/test/java/org/gridsuite/computation/RestResponseEntityExceptionHandlerTest.java b/src/test/java/org/gridsuite/computation/error/RestResponseEntityExceptionHandlerTest.java similarity index 74% rename from src/test/java/org/gridsuite/computation/RestResponseEntityExceptionHandlerTest.java rename to src/test/java/org/gridsuite/computation/error/RestResponseEntityExceptionHandlerTest.java index 008d346..ca86ad5 100644 --- a/src/test/java/org/gridsuite/computation/RestResponseEntityExceptionHandlerTest.java +++ b/src/test/java/org/gridsuite/computation/error/RestResponseEntityExceptionHandlerTest.java @@ -4,14 +4,15 @@ * 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.computation; +package org.gridsuite.computation.error; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.powsybl.ws.commons.error.PowsyblWsProblemDetail; -import org.gridsuite.computation.error.ComputationException; -import org.gridsuite.computation.error.RestResponseEntityExceptionHandler; +import org.gridsuite.computation.error.utils.SpecificErrorCode; +import org.gridsuite.computation.error.utils.TestRestResponseEntityExceptionHandler; +import org.gridsuite.computation.error.utils.TestTypedRestResponseEntityException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.http.HttpHeaders; @@ -84,17 +85,25 @@ void propagatesRemoteErrorDetails() throws JsonProcessingException { assertThat(response.getBody().getChain()).hasSize(1); } - private static final class TestRestResponseEntityExceptionHandler extends RestResponseEntityExceptionHandler { - private TestRestResponseEntityExceptionHandler() { - super(() -> "computation-server"); - } + @Test + void mapsSpecificBusinessErrorToTypedStatus() { + TestTypedRestResponseEntityException typed = new TestTypedRestResponseEntityException(); + ResponseEntity response = + typed.invokeHandle(SpecificErrorCode.MISC); - ResponseEntity invokeHandleDomainException(ComputationException exception, MockHttpServletRequest request) { - return super.handleDomainException(exception, request); - } + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); + assertThat(response.getBody()).isNotNull(); + assertEquals("specific.misc", response.getBody().getBusinessErrorCode()); + } - ResponseEntity invokeHandleRemoteException(HttpClientErrorException exception, MockHttpServletRequest request) { - return super.handleRemoteException(exception, request); - } + @Test + void delegatesComputationBusinessErrorToSuperHandler() { + TestTypedRestResponseEntityException typed = new TestTypedRestResponseEntityException(); + ResponseEntity response = + typed.invokeHandle(ComputationBusinessErrorCode.RESULT_NOT_FOUND); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); + assertThat(response.getBody()).isNotNull(); + assertEquals("computation.resultNotFound", response.getBody().getBusinessErrorCode()); } } diff --git a/src/test/java/org/gridsuite/computation/error/utils/SpecificErrorCode.java b/src/test/java/org/gridsuite/computation/error/utils/SpecificErrorCode.java new file mode 100644 index 0000000..004b9ab --- /dev/null +++ b/src/test/java/org/gridsuite/computation/error/utils/SpecificErrorCode.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.computation.error.utils; + +import com.powsybl.ws.commons.error.BusinessErrorCode; + + +/** + * @author Hugo Marcellin + */ +public enum SpecificErrorCode implements BusinessErrorCode { + MISC("specific.misc"); + private final String code; + SpecificErrorCode(String code) { + this.code = code; + } + public String value() { + return code; + } +} diff --git a/src/test/java/org/gridsuite/computation/error/utils/SpecificException.java b/src/test/java/org/gridsuite/computation/error/utils/SpecificException.java new file mode 100644 index 0000000..14438e7 --- /dev/null +++ b/src/test/java/org/gridsuite/computation/error/utils/SpecificException.java @@ -0,0 +1,30 @@ +/** + * 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.computation.error.utils; + +import com.powsybl.ws.commons.error.AbstractBusinessException; +import lombok.NonNull; + +import java.util.Objects; + +/** + * @author Hugo Marcellin + */ +public class SpecificException extends AbstractBusinessException { + + private final SpecificErrorCode errorCode; + + public SpecificException(SpecificErrorCode 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 SpecificErrorCode getBusinessErrorCode() { + return errorCode; + } +} \ No newline at end of file diff --git a/src/test/java/org/gridsuite/computation/error/utils/TestRestResponseEntityExceptionHandler.java b/src/test/java/org/gridsuite/computation/error/utils/TestRestResponseEntityExceptionHandler.java new file mode 100644 index 0000000..7dc2292 --- /dev/null +++ b/src/test/java/org/gridsuite/computation/error/utils/TestRestResponseEntityExceptionHandler.java @@ -0,0 +1,31 @@ +/** + * 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.computation.error.utils; + +import com.powsybl.ws.commons.error.PowsyblWsProblemDetail; +import org.gridsuite.computation.error.ComputationException; +import org.gridsuite.computation.error.ComputationRestResponseEntityExceptionHandler; +import org.springframework.http.ResponseEntity; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.web.client.HttpClientErrorException; + +/** + * @author Hugo Marcellin + */ +public class TestRestResponseEntityExceptionHandler extends ComputationRestResponseEntityExceptionHandler { + public TestRestResponseEntityExceptionHandler() { + super(() -> "computation-server"); + } + + public ResponseEntity invokeHandleDomainException(ComputationException exception, MockHttpServletRequest request) { + return super.handleDomainException(exception, request); + } + + public ResponseEntity invokeHandleRemoteException(HttpClientErrorException exception, MockHttpServletRequest request) { + return super.handleRemoteException(exception, request); + } +} \ No newline at end of file diff --git a/src/test/java/org/gridsuite/computation/error/utils/TestTypedRestResponseEntityException.java b/src/test/java/org/gridsuite/computation/error/utils/TestTypedRestResponseEntityException.java new file mode 100644 index 0000000..8e283ab --- /dev/null +++ b/src/test/java/org/gridsuite/computation/error/utils/TestTypedRestResponseEntityException.java @@ -0,0 +1,40 @@ +/** + * 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.computation.error.utils; + +import com.powsybl.ws.commons.error.PowsyblWsProblemDetail; +import org.gridsuite.computation.error.ComputationBusinessErrorCode; +import org.gridsuite.computation.error.ComputationException; +import org.gridsuite.computation.error.TypedComputationRestResponseEntityExceptionHandler; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.mock.web.MockHttpServletRequest; + +public class TestTypedRestResponseEntityException extends TypedComputationRestResponseEntityExceptionHandler { + public TestTypedRestResponseEntityException() { + super(() -> "computation-server", SpecificErrorCode.class); + } + + @Override + protected HttpStatus mapSpecificStatus(SpecificErrorCode code) { + return switch (code) { + case MISC -> HttpStatus.INTERNAL_SERVER_ERROR; + }; + } + + public ResponseEntity invokeHandle(SpecificErrorCode code) { + SpecificException exception = new SpecificException(code, "msg"); + return handleDomainException(exception, new MockHttpServletRequest("GET", "/test")); + } + + public ResponseEntity invokeHandle(ComputationBusinessErrorCode code) { + ComputationException exception = new ComputationException(code, "msg"); + return handleDomainException(exception, new MockHttpServletRequest("GET", "/test")); + } +} + + From 2153aaec332cc8fca4728430b82fa94e90ee97c2 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Wed, 26 Nov 2025 15:48:15 +0100 Subject: [PATCH 23/28] Checkstyle --- src/main/java/org/gridsuite/computation/utils/FilterUtils.java | 1 - .../error/utils/TestRestResponseEntityExceptionHandler.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/gridsuite/computation/utils/FilterUtils.java b/src/main/java/org/gridsuite/computation/utils/FilterUtils.java index 094acc0..6cead98 100644 --- a/src/main/java/org/gridsuite/computation/utils/FilterUtils.java +++ b/src/main/java/org/gridsuite/computation/utils/FilterUtils.java @@ -16,7 +16,6 @@ import java.io.UncheckedIOException; import java.util.List; - /** * @author maissa Souissi */ diff --git a/src/test/java/org/gridsuite/computation/error/utils/TestRestResponseEntityExceptionHandler.java b/src/test/java/org/gridsuite/computation/error/utils/TestRestResponseEntityExceptionHandler.java index 7dc2292..6170d85 100644 --- a/src/test/java/org/gridsuite/computation/error/utils/TestRestResponseEntityExceptionHandler.java +++ b/src/test/java/org/gridsuite/computation/error/utils/TestRestResponseEntityExceptionHandler.java @@ -28,4 +28,4 @@ public ResponseEntity invokeHandleDomainException(Comput public ResponseEntity invokeHandleRemoteException(HttpClientErrorException exception, MockHttpServletRequest request) { return super.handleRemoteException(exception, request); } -} \ No newline at end of file +} From a0e323ae81672af68ac57484436bfeff4823ba9e Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Wed, 26 Nov 2025 15:50:58 +0100 Subject: [PATCH 24/28] Checkstyle --- .../TypedComputationRestResponseEntityExceptionHandler.java | 2 +- .../gridsuite/computation/error/utils/SpecificErrorCode.java | 3 +++ .../gridsuite/computation/error/utils/SpecificException.java | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/gridsuite/computation/error/TypedComputationRestResponseEntityExceptionHandler.java b/src/main/java/org/gridsuite/computation/error/TypedComputationRestResponseEntityExceptionHandler.java index 896b0da..4e43760 100644 --- a/src/main/java/org/gridsuite/computation/error/TypedComputationRestResponseEntityExceptionHandler.java +++ b/src/main/java/org/gridsuite/computation/error/TypedComputationRestResponseEntityExceptionHandler.java @@ -14,7 +14,7 @@ * @author Hugo Marcellin */ -public abstract class TypedComputationRestResponseEntityExceptionHandler extends ComputationRestResponseEntityExceptionHandler { +public abstract class TypedComputationRestResponseEntityExceptionHandler extends ComputationRestResponseEntityExceptionHandler { private final Class specificComputationBusinessErrorCode; protected TypedComputationRestResponseEntityExceptionHandler(ServerNameProvider serverNameProvider, Class specificComputationBusinessErrorCode) { diff --git a/src/test/java/org/gridsuite/computation/error/utils/SpecificErrorCode.java b/src/test/java/org/gridsuite/computation/error/utils/SpecificErrorCode.java index 004b9ab..db86966 100644 --- a/src/test/java/org/gridsuite/computation/error/utils/SpecificErrorCode.java +++ b/src/test/java/org/gridsuite/computation/error/utils/SpecificErrorCode.java @@ -14,10 +14,13 @@ */ public enum SpecificErrorCode implements BusinessErrorCode { MISC("specific.misc"); + private final String code; + SpecificErrorCode(String code) { this.code = code; } + public String value() { return code; } diff --git a/src/test/java/org/gridsuite/computation/error/utils/SpecificException.java b/src/test/java/org/gridsuite/computation/error/utils/SpecificException.java index 14438e7..9fa0338 100644 --- a/src/test/java/org/gridsuite/computation/error/utils/SpecificException.java +++ b/src/test/java/org/gridsuite/computation/error/utils/SpecificException.java @@ -27,4 +27,4 @@ public SpecificException(SpecificErrorCode errorCode, String message) { public @NonNull SpecificErrorCode getBusinessErrorCode() { return errorCode; } -} \ No newline at end of file +} From cea13c20d1a93fd8cd7a64aedfa08530fb13a00b Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Wed, 26 Nov 2025 15:56:51 +0100 Subject: [PATCH 25/28] Rename class --- ...ctTypedComputationRestResponseEntityExceptionHandler.java} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename src/main/java/org/gridsuite/computation/error/{TypedComputationRestResponseEntityExceptionHandler.java => AbstractTypedComputationRestResponseEntityExceptionHandler.java} (79%) diff --git a/src/main/java/org/gridsuite/computation/error/TypedComputationRestResponseEntityExceptionHandler.java b/src/main/java/org/gridsuite/computation/error/AbstractTypedComputationRestResponseEntityExceptionHandler.java similarity index 79% rename from src/main/java/org/gridsuite/computation/error/TypedComputationRestResponseEntityExceptionHandler.java rename to src/main/java/org/gridsuite/computation/error/AbstractTypedComputationRestResponseEntityExceptionHandler.java index 4e43760..7eeeefe 100644 --- a/src/main/java/org/gridsuite/computation/error/TypedComputationRestResponseEntityExceptionHandler.java +++ b/src/main/java/org/gridsuite/computation/error/AbstractTypedComputationRestResponseEntityExceptionHandler.java @@ -14,10 +14,10 @@ * @author Hugo Marcellin */ -public abstract class TypedComputationRestResponseEntityExceptionHandler extends ComputationRestResponseEntityExceptionHandler { +public abstract class AbstractTypedComputationRestResponseEntityExceptionHandler extends ComputationRestResponseEntityExceptionHandler { private final Class specificComputationBusinessErrorCode; - protected TypedComputationRestResponseEntityExceptionHandler(ServerNameProvider serverNameProvider, Class specificComputationBusinessErrorCode) { + protected AbstractTypedComputationRestResponseEntityExceptionHandler(ServerNameProvider serverNameProvider, Class specificComputationBusinessErrorCode) { super(serverNameProvider); this.specificComputationBusinessErrorCode = specificComputationBusinessErrorCode; } From a3afc91522c1deb9cb332833110973b30104ae63 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Wed, 26 Nov 2025 15:59:16 +0100 Subject: [PATCH 26/28] Checkstyle --- .../error/utils/TestTypedRestResponseEntityException.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/gridsuite/computation/error/utils/TestTypedRestResponseEntityException.java b/src/test/java/org/gridsuite/computation/error/utils/TestTypedRestResponseEntityException.java index 8e283ab..c5a1be6 100644 --- a/src/test/java/org/gridsuite/computation/error/utils/TestTypedRestResponseEntityException.java +++ b/src/test/java/org/gridsuite/computation/error/utils/TestTypedRestResponseEntityException.java @@ -7,14 +7,14 @@ package org.gridsuite.computation.error.utils; import com.powsybl.ws.commons.error.PowsyblWsProblemDetail; +import org.gridsuite.computation.error.AbstractTypedComputationRestResponseEntityExceptionHandler; import org.gridsuite.computation.error.ComputationBusinessErrorCode; import org.gridsuite.computation.error.ComputationException; -import org.gridsuite.computation.error.TypedComputationRestResponseEntityExceptionHandler; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.mock.web.MockHttpServletRequest; -public class TestTypedRestResponseEntityException extends TypedComputationRestResponseEntityExceptionHandler { +public class TestTypedRestResponseEntityException extends AbstractTypedComputationRestResponseEntityExceptionHandler { public TestTypedRestResponseEntityException() { super(() -> "computation-server", SpecificErrorCode.class); } From 4b94989b371264dc47bf81d565363e1db61aa5c8 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Thu, 27 Nov 2025 14:47:34 +0100 Subject: [PATCH 27/28] Use new AbstractBusinessExceptionHandler and remove abstract typed computation exception handler --- pom.xml | 4 ++ ...ionRestResponseEntityExceptionHandler.java | 36 ------------ ...ionRestResponseEntityExceptionHandler.java | 15 ++--- ...estResponseEntityExceptionHandlerTest.java | 57 ------------------- .../error/utils/SpecificErrorCode.java | 27 --------- .../error/utils/SpecificException.java | 30 ---------- ...estRestResponseEntityExceptionHandler.java | 5 -- .../TestTypedRestResponseEntityException.java | 40 ------------- 8 files changed, 8 insertions(+), 206 deletions(-) delete mode 100644 src/main/java/org/gridsuite/computation/error/AbstractTypedComputationRestResponseEntityExceptionHandler.java delete mode 100644 src/test/java/org/gridsuite/computation/error/utils/SpecificErrorCode.java delete mode 100644 src/test/java/org/gridsuite/computation/error/utils/SpecificException.java delete mode 100644 src/test/java/org/gridsuite/computation/error/utils/TestTypedRestResponseEntityException.java diff --git a/pom.xml b/pom.xml index 0a8f96e..57e456a 100644 --- a/pom.xml +++ b/pom.xml @@ -50,6 +50,9 @@ gridsuite org.gridsuite:computation + + + 1.34.0-SNAPSHOT @@ -173,6 +176,7 @@ com.powsybl powsybl-ws-commons + ${powsybl-ws-commons.version} true diff --git a/src/main/java/org/gridsuite/computation/error/AbstractTypedComputationRestResponseEntityExceptionHandler.java b/src/main/java/org/gridsuite/computation/error/AbstractTypedComputationRestResponseEntityExceptionHandler.java deleted file mode 100644 index 7eeeefe..0000000 --- a/src/main/java/org/gridsuite/computation/error/AbstractTypedComputationRestResponseEntityExceptionHandler.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * 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.computation.error; - -import com.powsybl.ws.commons.error.BusinessErrorCode; -import com.powsybl.ws.commons.error.ServerNameProvider; -import org.springframework.http.HttpStatus; - -/** - * @author Hugo Marcellin - */ - -public abstract class AbstractTypedComputationRestResponseEntityExceptionHandler extends ComputationRestResponseEntityExceptionHandler { - private final Class specificComputationBusinessErrorCode; - - protected AbstractTypedComputationRestResponseEntityExceptionHandler(ServerNameProvider serverNameProvider, Class specificComputationBusinessErrorCode) { - super(serverNameProvider); - this.specificComputationBusinessErrorCode = specificComputationBusinessErrorCode; - } - - @Override - protected HttpStatus mapStatus(BusinessErrorCode businessErrorCode) { - if (businessErrorCode instanceof ComputationBusinessErrorCode computationCode) { - return super.mapStatus(computationCode); - } else if (specificComputationBusinessErrorCode.isInstance(businessErrorCode)) { - return mapSpecificStatus(specificComputationBusinessErrorCode.cast(businessErrorCode)); - } - return HttpStatus.INTERNAL_SERVER_ERROR; - } - - protected abstract HttpStatus mapSpecificStatus(C code); -} diff --git a/src/main/java/org/gridsuite/computation/error/ComputationRestResponseEntityExceptionHandler.java b/src/main/java/org/gridsuite/computation/error/ComputationRestResponseEntityExceptionHandler.java index 89064ab..9eab305 100644 --- a/src/main/java/org/gridsuite/computation/error/ComputationRestResponseEntityExceptionHandler.java +++ b/src/main/java/org/gridsuite/computation/error/ComputationRestResponseEntityExceptionHandler.java @@ -6,37 +6,30 @@ */ package org.gridsuite.computation.error; -import com.powsybl.ws.commons.error.AbstractBaseRestExceptionHandler; -import com.powsybl.ws.commons.error.AbstractBusinessException; -import com.powsybl.ws.commons.error.BusinessErrorCode; +import com.powsybl.ws.commons.error.AbstractBusinessExceptionHandler; import com.powsybl.ws.commons.error.ServerNameProvider; import lombok.NonNull; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ControllerAdvice; -import static org.gridsuite.computation.error.ComputationBusinessErrorCode.INVALID_EXPORT_PARAMS; -import static org.gridsuite.computation.error.ComputationBusinessErrorCode.INVALID_SORT_FORMAT; -import static org.gridsuite.computation.error.ComputationBusinessErrorCode.PARAMETERS_NOT_FOUND; -import static org.gridsuite.computation.error.ComputationBusinessErrorCode.RESULT_NOT_FOUND; - /** * @author Hugo Marcellin */ @ControllerAdvice -public class ComputationRestResponseEntityExceptionHandler extends AbstractBaseRestExceptionHandler { +public class ComputationRestResponseEntityExceptionHandler extends AbstractBusinessExceptionHandler { protected ComputationRestResponseEntityExceptionHandler(ServerNameProvider serverNameProvider) { super(serverNameProvider); } @Override - protected @NonNull BusinessErrorCode getBusinessCode(AbstractBusinessException e) { + protected @NonNull ComputationBusinessErrorCode getBusinessCode(ComputationException e) { return e.getBusinessErrorCode(); } @Override - protected HttpStatus mapStatus(BusinessErrorCode businessErrorCode) { + protected HttpStatus mapStatus(ComputationBusinessErrorCode businessErrorCode) { return switch (businessErrorCode) { case RESULT_NOT_FOUND, PARAMETERS_NOT_FOUND -> HttpStatus.NOT_FOUND; case INVALID_SORT_FORMAT, INVALID_EXPORT_PARAMS -> HttpStatus.BAD_REQUEST; diff --git a/src/test/java/org/gridsuite/computation/error/RestResponseEntityExceptionHandlerTest.java b/src/test/java/org/gridsuite/computation/error/RestResponseEntityExceptionHandlerTest.java index ca86ad5..f4c8ac7 100644 --- a/src/test/java/org/gridsuite/computation/error/RestResponseEntityExceptionHandlerTest.java +++ b/src/test/java/org/gridsuite/computation/error/RestResponseEntityExceptionHandlerTest.java @@ -6,20 +6,13 @@ */ package org.gridsuite.computation.error; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.powsybl.ws.commons.error.PowsyblWsProblemDetail; -import org.gridsuite.computation.error.utils.SpecificErrorCode; import org.gridsuite.computation.error.utils.TestRestResponseEntityExceptionHandler; -import org.gridsuite.computation.error.utils.TestTypedRestResponseEntityException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.web.client.HttpClientErrorException; import static org.assertj.core.api.Assertions.assertThat; import static org.gridsuite.computation.error.ComputationBusinessErrorCode.INVALID_SORT_FORMAT; @@ -28,8 +21,6 @@ class RestResponseEntityExceptionHandlerTest { - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper().registerModule(new JavaTimeModule()); - private TestRestResponseEntityExceptionHandler handler; @BeforeEach @@ -58,52 +49,4 @@ void mapsBadRequestBusinessErrorToStatus() { assertThat(response.getBody()).isNotNull(); assertEquals("computation.invalidSortFormat", response.getBody().getBusinessErrorCode()); } - - @Test - void propagatesRemoteErrorDetails() throws JsonProcessingException { - MockHttpServletRequest request = new MockHttpServletRequest("GET", "/computations/remote"); - PowsyblWsProblemDetail remote = PowsyblWsProblemDetail.builder(HttpStatus.INTERNAL_SERVER_ERROR) - .server("computation") - .businessErrorCode("computation.remoteError") - .detail("Computation failure") - .path("/computation") - .build(); - - HttpClientErrorException exception = HttpClientErrorException.create( - HttpStatus.INTERNAL_SERVER_ERROR, - "error", - HttpHeaders.EMPTY, - OBJECT_MAPPER.writeValueAsBytes(remote), - null - ); - - ResponseEntity response = handler.invokeHandleRemoteException(exception, request); - - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); - assertThat(response.getBody()).isNotNull(); - assertEquals("computation.remoteError", response.getBody().getBusinessErrorCode()); - assertThat(response.getBody().getChain()).hasSize(1); - } - - @Test - void mapsSpecificBusinessErrorToTypedStatus() { - TestTypedRestResponseEntityException typed = new TestTypedRestResponseEntityException(); - ResponseEntity response = - typed.invokeHandle(SpecificErrorCode.MISC); - - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); - assertThat(response.getBody()).isNotNull(); - assertEquals("specific.misc", response.getBody().getBusinessErrorCode()); - } - - @Test - void delegatesComputationBusinessErrorToSuperHandler() { - TestTypedRestResponseEntityException typed = new TestTypedRestResponseEntityException(); - ResponseEntity response = - typed.invokeHandle(ComputationBusinessErrorCode.RESULT_NOT_FOUND); - - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - assertThat(response.getBody()).isNotNull(); - assertEquals("computation.resultNotFound", response.getBody().getBusinessErrorCode()); - } } diff --git a/src/test/java/org/gridsuite/computation/error/utils/SpecificErrorCode.java b/src/test/java/org/gridsuite/computation/error/utils/SpecificErrorCode.java deleted file mode 100644 index db86966..0000000 --- a/src/test/java/org/gridsuite/computation/error/utils/SpecificErrorCode.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * 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.computation.error.utils; - -import com.powsybl.ws.commons.error.BusinessErrorCode; - - -/** - * @author Hugo Marcellin - */ -public enum SpecificErrorCode implements BusinessErrorCode { - MISC("specific.misc"); - - private final String code; - - SpecificErrorCode(String code) { - this.code = code; - } - - public String value() { - return code; - } -} diff --git a/src/test/java/org/gridsuite/computation/error/utils/SpecificException.java b/src/test/java/org/gridsuite/computation/error/utils/SpecificException.java deleted file mode 100644 index 9fa0338..0000000 --- a/src/test/java/org/gridsuite/computation/error/utils/SpecificException.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * 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.computation.error.utils; - -import com.powsybl.ws.commons.error.AbstractBusinessException; -import lombok.NonNull; - -import java.util.Objects; - -/** - * @author Hugo Marcellin - */ -public class SpecificException extends AbstractBusinessException { - - private final SpecificErrorCode errorCode; - - public SpecificException(SpecificErrorCode 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 SpecificErrorCode getBusinessErrorCode() { - return errorCode; - } -} diff --git a/src/test/java/org/gridsuite/computation/error/utils/TestRestResponseEntityExceptionHandler.java b/src/test/java/org/gridsuite/computation/error/utils/TestRestResponseEntityExceptionHandler.java index 6170d85..6ca094d 100644 --- a/src/test/java/org/gridsuite/computation/error/utils/TestRestResponseEntityExceptionHandler.java +++ b/src/test/java/org/gridsuite/computation/error/utils/TestRestResponseEntityExceptionHandler.java @@ -11,7 +11,6 @@ import org.gridsuite.computation.error.ComputationRestResponseEntityExceptionHandler; import org.springframework.http.ResponseEntity; import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.web.client.HttpClientErrorException; /** * @author Hugo Marcellin @@ -24,8 +23,4 @@ public TestRestResponseEntityExceptionHandler() { public ResponseEntity invokeHandleDomainException(ComputationException exception, MockHttpServletRequest request) { return super.handleDomainException(exception, request); } - - public ResponseEntity invokeHandleRemoteException(HttpClientErrorException exception, MockHttpServletRequest request) { - return super.handleRemoteException(exception, request); - } } diff --git a/src/test/java/org/gridsuite/computation/error/utils/TestTypedRestResponseEntityException.java b/src/test/java/org/gridsuite/computation/error/utils/TestTypedRestResponseEntityException.java deleted file mode 100644 index c5a1be6..0000000 --- a/src/test/java/org/gridsuite/computation/error/utils/TestTypedRestResponseEntityException.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * 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.computation.error.utils; - -import com.powsybl.ws.commons.error.PowsyblWsProblemDetail; -import org.gridsuite.computation.error.AbstractTypedComputationRestResponseEntityExceptionHandler; -import org.gridsuite.computation.error.ComputationBusinessErrorCode; -import org.gridsuite.computation.error.ComputationException; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.mock.web.MockHttpServletRequest; - -public class TestTypedRestResponseEntityException extends AbstractTypedComputationRestResponseEntityExceptionHandler { - public TestTypedRestResponseEntityException() { - super(() -> "computation-server", SpecificErrorCode.class); - } - - @Override - protected HttpStatus mapSpecificStatus(SpecificErrorCode code) { - return switch (code) { - case MISC -> HttpStatus.INTERNAL_SERVER_ERROR; - }; - } - - public ResponseEntity invokeHandle(SpecificErrorCode code) { - SpecificException exception = new SpecificException(code, "msg"); - return handleDomainException(exception, new MockHttpServletRequest("GET", "/test")); - } - - public ResponseEntity invokeHandle(ComputationBusinessErrorCode code) { - ComputationException exception = new ComputationException(code, "msg"); - return handleDomainException(exception, new MockHttpServletRequest("GET", "/test")); - } -} - - From 2d2fc312519e9e0a09fe25a46d2bedf196e32117 Mon Sep 17 00:00:00 2001 From: Hugo Marcellin Date: Thu, 27 Nov 2025 17:06:11 +0100 Subject: [PATCH 28/28] Rename handlers and make them handle their own exceptions to avoid conflicts --- ...andler.java => ComputationExceptionHandler.java} | 13 +++++++++++-- .../TestRestResponseEntityExceptionHandler.java | 4 ++-- 2 files changed, 13 insertions(+), 4 deletions(-) rename src/main/java/org/gridsuite/computation/error/{ComputationRestResponseEntityExceptionHandler.java => ComputationExceptionHandler.java} (63%) diff --git a/src/main/java/org/gridsuite/computation/error/ComputationRestResponseEntityExceptionHandler.java b/src/main/java/org/gridsuite/computation/error/ComputationExceptionHandler.java similarity index 63% rename from src/main/java/org/gridsuite/computation/error/ComputationRestResponseEntityExceptionHandler.java rename to src/main/java/org/gridsuite/computation/error/ComputationExceptionHandler.java index 9eab305..f8a7d2e 100644 --- a/src/main/java/org/gridsuite/computation/error/ComputationRestResponseEntityExceptionHandler.java +++ b/src/main/java/org/gridsuite/computation/error/ComputationExceptionHandler.java @@ -7,19 +7,23 @@ package org.gridsuite.computation.error; import com.powsybl.ws.commons.error.AbstractBusinessExceptionHandler; +import com.powsybl.ws.commons.error.PowsyblWsProblemDetail; import com.powsybl.ws.commons.error.ServerNameProvider; +import jakarta.servlet.http.HttpServletRequest; import lombok.NonNull; import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; /** * @author Hugo Marcellin */ @ControllerAdvice -public class ComputationRestResponseEntityExceptionHandler extends AbstractBusinessExceptionHandler { +public class ComputationExceptionHandler extends AbstractBusinessExceptionHandler { - protected ComputationRestResponseEntityExceptionHandler(ServerNameProvider serverNameProvider) { + protected ComputationExceptionHandler(ServerNameProvider serverNameProvider) { super(serverNameProvider); } @@ -36,4 +40,9 @@ protected HttpStatus mapStatus(ComputationBusinessErrorCode businessErrorCode) { default -> HttpStatus.INTERNAL_SERVER_ERROR; }; } + + @ExceptionHandler(ComputationException.class) + public ResponseEntity handleComputationException(ComputationException exception, HttpServletRequest request) { + return super.handleDomainException(exception, request); + } } diff --git a/src/test/java/org/gridsuite/computation/error/utils/TestRestResponseEntityExceptionHandler.java b/src/test/java/org/gridsuite/computation/error/utils/TestRestResponseEntityExceptionHandler.java index 6ca094d..d87d732 100644 --- a/src/test/java/org/gridsuite/computation/error/utils/TestRestResponseEntityExceptionHandler.java +++ b/src/test/java/org/gridsuite/computation/error/utils/TestRestResponseEntityExceptionHandler.java @@ -8,14 +8,14 @@ import com.powsybl.ws.commons.error.PowsyblWsProblemDetail; import org.gridsuite.computation.error.ComputationException; -import org.gridsuite.computation.error.ComputationRestResponseEntityExceptionHandler; +import org.gridsuite.computation.error.ComputationExceptionHandler; import org.springframework.http.ResponseEntity; import org.springframework.mock.web.MockHttpServletRequest; /** * @author Hugo Marcellin */ -public class TestRestResponseEntityExceptionHandler extends ComputationRestResponseEntityExceptionHandler { +public class TestRestResponseEntityExceptionHandler extends ComputationExceptionHandler { public TestRestResponseEntityExceptionHandler() { super(() -> "computation-server"); }