Skip to content

Commit 101ac8b

Browse files
authored
Harmonize exceptions handling (#129)
Signed-off-by: Hugo Marcellin <[email protected]>
1 parent f35660c commit 101ac8b

File tree

12 files changed

+237
-8
lines changed

12 files changed

+237
-8
lines changed

pom.xml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@
5656
<liquibase-hibernate-package>org.gridsuite.voltageinit.server</liquibase-hibernate-package>
5757
<sonar.organization>gridsuite</sonar.organization>
5858
<sonar.projectKey>org.gridsuite:voltage-init-server</sonar.projectKey>
59+
<!-- To remove after when using gridsuite dependencies release and computation version containing merged PR: https://github.com/gridsuite/computation/pull/19 -->
60+
<gridsuite-computation.version>1.7.0</gridsuite-computation.version>
61+
<powsybl-ws-commons.version>1.34.0</powsybl-ws-commons.version>
62+
<gridsuite-filter.version>1.15.0</gridsuite-filter.version>
5963
</properties>
6064

6165
<build>
@@ -90,6 +94,24 @@
9094

9195
<dependencyManagement>
9296
<dependencies>
97+
<!-- overrides of imports -->
98+
<dependency>
99+
<groupId>com.powsybl</groupId>
100+
<artifactId>powsybl-ws-commons</artifactId>
101+
<version>${powsybl-ws-commons.version}</version>
102+
</dependency>
103+
104+
<dependency>
105+
<groupId>org.gridsuite</groupId>
106+
<artifactId>gridsuite-computation</artifactId>
107+
<version>${gridsuite-computation.version}</version>
108+
</dependency>
109+
110+
<dependency>
111+
<groupId>org.gridsuite</groupId>
112+
<artifactId>gridsuite-filter</artifactId>
113+
<version>${gridsuite-filter.version}</version>
114+
</dependency>
93115

94116
<dependency><!-- To remove when integrate in next release of gridsuite-dependencies or powsybl-ws-dependencies -->
95117
<groupId>com.squareup.okhttp3</groupId>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
package org.gridsuite.voltageinit.server;
8+
9+
import com.powsybl.ws.commons.error.ServerNameProvider;
10+
import org.springframework.beans.factory.annotation.Value;
11+
import org.springframework.stereotype.Component;
12+
13+
/**
14+
* @author Hugo Marcellin <hugo.marcelin at rte-france.com>
15+
*/
16+
@Component
17+
public class PropertyServerNameProvider implements ServerNameProvider {
18+
19+
private final String name;
20+
21+
public PropertyServerNameProvider(@Value("${spring.application.name:voltage-init-server}") String name) {
22+
this.name = name;
23+
}
24+
25+
@Override
26+
public String serverName() {
27+
return name;
28+
}
29+
}

src/main/java/org/gridsuite/voltageinit/server/VoltageInitApplication.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package org.gridsuite.voltageinit.server;
88

99
import com.powsybl.network.store.client.NetworkStoreService;
10+
import org.gridsuite.computation.error.ComputationExceptionHandler;
1011
import org.gridsuite.computation.service.NotificationService;
1112
import org.springframework.boot.SpringApplication;
1213
import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -15,7 +16,7 @@
1516
* @author Etienne Homer <etienne.homer at rte-france.com>
1617
*/
1718
@SuppressWarnings("checkstyle:HideUtilityClassConstructor")
18-
@SpringBootApplication(scanBasePackageClasses = { VoltageInitApplication.class, NetworkStoreService.class, NotificationService.class })
19+
@SpringBootApplication(scanBasePackageClasses = {VoltageInitApplication.class, NetworkStoreService.class, NotificationService.class, ComputationExceptionHandler.class})
1920
public class VoltageInitApplication {
2021
public static void main(String[] args) {
2122
SpringApplication.run(VoltageInitApplication.class, args);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Copyright (c) 2017-2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
* SPDX-License-Identifier: MPL-2.0
7+
*/
8+
package org.gridsuite.voltageinit.server.error;
9+
10+
import com.powsybl.ws.commons.error.BusinessErrorCode;
11+
12+
/**
13+
* @author Hugo Marcellin <hugo.marcelin at rte-france.com>
14+
*/
15+
public enum VoltageInitBusinessErrorCode implements BusinessErrorCode {
16+
MISSING_FILTER("voltageInit.missingFilter");
17+
18+
private final String code;
19+
20+
VoltageInitBusinessErrorCode(String code) {
21+
this.code = code;
22+
}
23+
24+
public String value() {
25+
return code;
26+
}
27+
}

src/main/java/org/gridsuite/voltageinit/server/error/VoltageInitException.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,25 @@
66
*/
77
package org.gridsuite.voltageinit.server.error;
88

9+
import com.powsybl.ws.commons.error.AbstractBusinessException;
10+
import lombok.NonNull;
11+
912
import java.util.Objects;
1013

1114
/**
1215
* @author Mohamed Ben-rejeb {@literal <mohamed.ben-rejeb at rte-france.com>}
1316
*/
14-
public class VoltageInitException extends RuntimeException {
17+
public class VoltageInitException extends AbstractBusinessException {
18+
19+
private final VoltageInitBusinessErrorCode errorCode;
1520

16-
public VoltageInitException(String message) {
21+
public VoltageInitException(VoltageInitBusinessErrorCode errorCode, String message) {
1722
super(Objects.requireNonNull(message, "message must not be null"));
23+
this.errorCode = Objects.requireNonNull(errorCode, "errorCode must not be null");
24+
}
25+
26+
@Override
27+
public @NonNull VoltageInitBusinessErrorCode getBusinessErrorCode() {
28+
return errorCode;
1829
}
1930
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
package org.gridsuite.voltageinit.server.error;
8+
9+
import com.powsybl.ws.commons.error.AbstractBusinessExceptionHandler;
10+
import com.powsybl.ws.commons.error.PowsyblWsProblemDetail;
11+
import com.powsybl.ws.commons.error.ServerNameProvider;
12+
import jakarta.servlet.http.HttpServletRequest;
13+
import lombok.NonNull;
14+
import org.springframework.http.HttpStatus;
15+
import org.springframework.http.ResponseEntity;
16+
import org.springframework.web.bind.annotation.ControllerAdvice;
17+
import org.springframework.web.bind.annotation.ExceptionHandler;
18+
19+
/**
20+
* @author Hugo Marcellin <hugo.marcelin at rte-france.com>
21+
*/
22+
@ControllerAdvice
23+
public class VoltageInitExceptionHandler extends AbstractBusinessExceptionHandler<VoltageInitException, VoltageInitBusinessErrorCode> {
24+
protected VoltageInitExceptionHandler(ServerNameProvider serverNameProvider) {
25+
super(serverNameProvider);
26+
}
27+
28+
@Override
29+
protected @NonNull VoltageInitBusinessErrorCode getBusinessCode(VoltageInitException e) {
30+
return e.getBusinessErrorCode();
31+
}
32+
33+
@Override
34+
protected HttpStatus mapStatus(VoltageInitBusinessErrorCode businessErrorCode) {
35+
return switch (businessErrorCode) {
36+
case MISSING_FILTER -> HttpStatus.INTERNAL_SERVER_ERROR;
37+
};
38+
}
39+
40+
@ExceptionHandler(VoltageInitException.class)
41+
protected ResponseEntity<PowsyblWsProblemDetail> handleVoltageInitException(
42+
VoltageInitException exception, HttpServletRequest request) {
43+
return super.handleDomainException(exception, request);
44+
}
45+
}

src/main/java/org/gridsuite/voltageinit/server/service/parameters/FilterService.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
import org.gridsuite.filter.AbstractFilter;
1616
import org.gridsuite.filter.utils.EquipmentType;
1717
import org.gridsuite.voltageinit.server.dto.parameters.FilterEquipments;
18+
import org.gridsuite.voltageinit.server.error.VoltageInitBusinessErrorCode;
1819
import org.gridsuite.voltageinit.server.error.VoltageInitException;
1920
import org.springframework.beans.factory.annotation.Value;
21+
import org.springframework.boot.web.client.RestTemplateBuilder;
2022
import org.springframework.core.ParameterizedTypeReference;
2123
import org.springframework.http.HttpMethod;
2224
import org.springframework.stereotype.Service;
@@ -45,9 +47,10 @@ public class FilterService extends AbstractFilterService {
4547

4648
public static final String FILTERS_NOT_FOUND = "Filters not found";
4749

48-
public FilterService(NetworkStoreService networkStoreService,
50+
public FilterService(RestTemplateBuilder restTemplateBuilder,
51+
NetworkStoreService networkStoreService,
4952
@Value("${gridsuite.services.filter-server.base-uri:http://filter-server/}") String filterServerBaseUri) {
50-
super(networkStoreService, filterServerBaseUri);
53+
super(restTemplateBuilder, networkStoreService, filterServerBaseUri);
5154
}
5255

5356
public List<FilterEquipments> exportFilters(List<UUID> filtersUuids, UUID networkUuid, String variantId) {
@@ -85,7 +88,7 @@ public void ensureFiltersExist(Map<UUID, String> filterNamesByUuid) {
8588
.filter(filterId -> !validFilters.contains(filterId))
8689
.toList();
8790
if (!missingFilters.isEmpty()) {
88-
throw new VoltageInitException(buildMissingFiltersMessage(missingFilters, filterNamesByUuid));
91+
throw new VoltageInitException(VoltageInitBusinessErrorCode.MISSING_FILTER, buildMissingFiltersMessage(missingFilters, filterNamesByUuid));
8992
}
9093
}
9194

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
package org.gridsuite.voltageinit.server;
8+
9+
import org.junit.jupiter.api.Test;
10+
11+
import static org.assertj.core.api.Assertions.assertThat;
12+
13+
/**
14+
* @author Hugo Marcellin <hugo.marcelin at rte-france.com>
15+
*/
16+
class PropertyServerNameProviderTest {
17+
18+
@Test
19+
void returnsProvidedName() {
20+
PropertyServerNameProvider provider = new PropertyServerNameProvider("custom-server");
21+
assertThat(provider.serverName()).isEqualTo("custom-server");
22+
}
23+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
package org.gridsuite.voltageinit.server;
8+
9+
import org.gridsuite.voltageinit.server.error.VoltageInitBusinessErrorCode;
10+
import org.junit.jupiter.params.ParameterizedTest;
11+
import org.junit.jupiter.params.provider.EnumSource;
12+
13+
import static org.gridsuite.voltageinit.utils.assertions.Assertions.assertThat;
14+
15+
/**
16+
* @author Hugo Marcellin <hugo.marcelin at rte-france.com>
17+
*/
18+
class VoltageInitBusinessErrorCodeTest {
19+
@ParameterizedTest
20+
@EnumSource(VoltageInitBusinessErrorCode.class)
21+
void valueMatchesEnumName(VoltageInitBusinessErrorCode code) {
22+
assertThat(code.value()).startsWith("voltageInit.");
23+
}
24+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
package org.gridsuite.voltageinit.server.error;
8+
9+
import com.powsybl.ws.commons.error.PowsyblWsProblemDetail;
10+
import org.junit.jupiter.api.BeforeEach;
11+
import org.junit.jupiter.api.Test;
12+
import org.springframework.http.HttpStatus;
13+
import org.springframework.http.ResponseEntity;
14+
import org.springframework.mock.web.MockHttpServletRequest;
15+
16+
import static org.assertj.core.api.Assertions.assertThat;
17+
import static org.gridsuite.voltageinit.server.error.VoltageInitBusinessErrorCode.MISSING_FILTER;
18+
import static org.junit.jupiter.api.Assertions.assertEquals;
19+
20+
/**
21+
* @author Hugo Marcellin <hugo.marcelin at rte-france.com>
22+
*/
23+
class VoltageInitExceptionHandlerTest {
24+
25+
private VoltageInitExceptionHandler handler;
26+
27+
@BeforeEach
28+
void setUp() {
29+
handler = new VoltageInitExceptionHandler(() -> "voltageInit");
30+
}
31+
32+
@Test
33+
void mapsInteralErrorBusinessErrorToStatus() {
34+
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/results-endpoint/uuid");
35+
VoltageInitException exception = new VoltageInitException(MISSING_FILTER, "Bus out of voltage");
36+
ResponseEntity<PowsyblWsProblemDetail> response = handler.handleVoltageInitException(exception, request);
37+
38+
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);
39+
assertThat(response.getBody()).isNotNull();
40+
assertEquals("voltageInit.missingFilter", response.getBody().getBusinessErrorCode());
41+
}
42+
}

0 commit comments

Comments
 (0)