Moving Dynamic Simulation params to dynamic-simulation-server#969
Moving Dynamic Simulation params to dynamic-simulation-server#969
Conversation
Signed-off-by: Thang PHAM <phamthang37@gmail.com>
Signed-off-by: Thang PHAM <phamthang37@gmail.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughDynamic-simulation parameters were converted from in-code DTO/entity objects to UUID-referenced serialized JSON. Controllers, services, and clients were updated to use parameter UUIDs and raw JSON strings; many DTOs/entities were removed; new parameter-management APIs and a DB migration were added. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Controller as StudyController
participant StudyService
participant DynamicSimulationService
participant DynamicSimulationClient
participant ExtSim as ExternalSimulationAPI
Client->>Controller: POST /studies/{id}/runDynamicSimulation?parametersUuid={uuid}\nbody: events JSON
Controller->>StudyService: runDynamicSimulation(studyUuid, nodeUuid, rootNetworkUuid, userId, debug)
StudyService->>DynamicSimulationService: runDynamicSimulation(nodeUuid, rootNetworkUuid, networkUuid, variantId, reportUuid, parametersUuid, events, userId, debug)
DynamicSimulationService->>DynamicSimulationClient: run(receiver, networkUuid, variantId, reportInfos, parametersUuid, events, userId, debug)
DynamicSimulationClient->>ExtSim: POST /api/dynamicsimulation/run?parametersUuid={uuid}\nbody: events
ExtSim-->>DynamicSimulationClient: 202 Accepted / resultUuid
DynamicSimulationClient-->>DynamicSimulationService: resultUuid
DynamicSimulationService-->>StudyService: resultUuid
StudyService-->>Controller: resultUuid
Controller-->>Client: 202 Accepted with resultUuid
Suggested reviewers
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
src/main/java/org/gridsuite/study/server/service/client/dynamicmargincalculation/DynamicMarginCalculationClient.java (1)
154-162:⚠️ Potential issue | 🟡 MinorAdd null validation for
dynamicSimulationParametersUuid.The parameter
dynamicSimulationParametersUuidis annotated with@NonNullbut lacks the correspondingObjects.requireNonNull()validation that other@NonNullparameters in this method have. This inconsistency could lead to less clear error messages ifnullis accidentally passed.Proposed fix
public UUID run(`@NonNull` String receiver, `@NonNull` UUID networkUuid, String variantId, `@NonNull` ReportInfos reportInfos, `@NonNull` UUID dynamicSimulationParametersUuid, `@NonNull` UUID dynamicSecurityAnalysisParametersUuid, `@NonNull` UUID parametersUuid, String userId, boolean debug) { Objects.requireNonNull(receiver); Objects.requireNonNull(networkUuid); Objects.requireNonNull(reportInfos); + Objects.requireNonNull(dynamicSimulationParametersUuid); Objects.requireNonNull(dynamicSecurityAnalysisParametersUuid); Objects.requireNonNull(parametersUuid);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/org/gridsuite/study/server/service/client/dynamicmargincalculation/DynamicMarginCalculationClient.java` around lines 154 - 162, The method run in DynamicMarginCalculationClient is missing a null-check for the `@NonNull` parameter dynamicSimulationParametersUuid; add an Objects.requireNonNull(dynamicSimulationParametersUuid) call in the same validation block where receiver, networkUuid, reportInfos, dynamicSecurityAnalysisParametersUuid, and parametersUuid are checked so the method consistently validates all `@NonNull` parameters and throws a clear NPE if dynamicSimulationParametersUuid is null.src/test/java/org/gridsuite/study/server/service/client/dynamicmargincalculation/DynamicMarginCalculationClientTest.java (2)
306-321:⚠️ Potential issue | 🟡 MinorWireMock stub missing
dynamicSimulationParametersUuidquery parameter validation.The stub validates
dynamicSecurityAnalysisParametersUuidandparametersUuidbut omits validation fordynamicSimulationParametersUuid. According to the production code, this parameter is sent as a query parameter (.queryParam("dynamicSimulationParametersUuid", dynamicSimulationParametersUuid)). The stub will accept any value for this parameter, reducing test coverage.🐛 Proposed fix to add missing query param validation
wireMockServer.stubFor(WireMock.post(WireMock.urlPathTemplate(url)) .withQueryParam(QUERY_PARAM_VARIANT_ID, equalTo("variantId")) + .withQueryParam("dynamicSimulationParametersUuid", equalTo(DYNAMIC_SIMULATION_PARAMETERS_UUID.toString())) .withQueryParam("dynamicSecurityAnalysisParametersUuid", equalTo(DYNAMIC_SECURITY_ANALYSIS_PARAMETERS_UUID.toString())) .withQueryParam("parametersUuid", equalTo(PARAMETERS_UUID.toString()))🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/test/java/org/gridsuite/study/server/service/client/dynamicmargincalculation/DynamicMarginCalculationClientTest.java` around lines 306 - 321, The WireMock stub in DynamicMarginCalculationClientTest is missing validation for the dynamicSimulationParametersUuid query parameter; update the stub chain (the WireMock.post(...).withQueryParam(...) calls) to include .withQueryParam("dynamicSimulationParametersUuid", equalTo(DYNAMIC_SIMULATION_PARAMETERS_UUID.toString())) so the stub matches the production call made by dynamicMarginCalculationClient.run and uses the existing DYNAMIC_SIMULATION_PARAMETERS_UUID test constant.
327-345:⚠️ Potential issue | 🟡 MinorError case WireMock stub also missing
dynamicSimulationParametersUuidvalidation.Same issue as the success case - the error stub should validate the
dynamicSimulationParametersUuidquery parameter for consistency.🐛 Proposed fix
wireMockServer.stubFor(WireMock.post(WireMock.urlPathTemplate(url)) .withQueryParam(QUERY_PARAM_VARIANT_ID, absent()) .withQueryParam("provider", absent()) + .withQueryParam("dynamicSimulationParametersUuid", equalTo(DYNAMIC_SIMULATION_PARAMETERS_UUID.toString())) .withQueryParam("dynamicSecurityAnalysisParametersUuid", equalTo(DYNAMIC_SECURITY_ANALYSIS_PARAMETERS_UUID.toString()))🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/test/java/org/gridsuite/study/server/service/client/dynamicmargincalculation/DynamicMarginCalculationClientTest.java` around lines 327 - 345, The WireMock error stub in DynamicMarginCalculationClientTest is missing validation for the dynamicSimulationParametersUuid query param; update the stub configured via wireMockServer.stubFor(...) (same block that uses url, QUERY_PARAM_VARIANT_ID, QUERY_PARAM_RECEIVER, etc.) to include .withQueryParam("dynamicSimulationParametersUuid", equalTo(DYNAMIC_SIMULATION_PARAMETERS_UUID.toString())) so the error case validates the dynamicSimulationParametersUuid the same way the success case does.
🧹 Nitpick comments (4)
src/main/resources/db/changelog/changesets/changelog_20260319T184344Z.xml (1)
6-7: Minor: Inconsistent table name casing.The changeset uses lowercase
studyon line 6 but uppercaseSTUDYon lines 11, 14, and 17. While Liquibase and most databases handle this gracefully, consistent casing improves readability.Suggested fix for consistency
<changeSet author="phamquy (generated)" id="1773945844517-17"> - <dropForeignKeyConstraint baseTableName="STUDY" constraintName="DYNAMICSIMULATIONPARAMETERS_ID_FK"/> + <dropForeignKeyConstraint baseTableName="study" constraintName="DYNAMICSIMULATIONPARAMETERS_ID_FK"/> </changeSet> <changeSet author="phamquy (generated)" id="1773945844517-18"> - <dropTable tableName="DYNAMIC_SIMULATION_PARAMETERS"/> + <dropTable tableName="dynamic_simulation_parameters"/> </changeSet> <changeSet author="phamquy (generated)" id="1773945844517-19"> - <dropColumn columnName="DYNAMIC_SIMULATION_PARAMETERS_ENTITY_ID" tableName="STUDY"/> + <dropColumn columnName="dynamic_simulation_parameters_entity_id" tableName="study"/> </changeSet> <changeSet author="phamquy (generated)" id="1773945844517-20"> - <dropColumn columnName="DYNAMIC_SIMULATION_PROVIDER" tableName="STUDY"/> + <dropColumn columnName="dynamic_simulation_provider" tableName="study"/> </changeSet>Also applies to: 11-11, 14-14, 17-17
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/resources/db/changelog/changesets/changelog_20260319T184344Z.xml` around lines 6 - 7, The XML changeset has inconsistent tableName casing: some tags use tableName="study" and others tableName="STUDY"; update all tableName attributes in this changeset to use a single consistent casing (pick one convention—prefer lowercase "study") for every change element (e.g., the <addColumn tableName="study"> and the other change elements referencing STUDY) so all occurrences match exactly for readability and consistency.src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/DynamicSimulationClient.java (1)
31-45: Consider consistent@NonNullannotations across similar parameter methods.
getProvideruses@NonNull UUID parametersUuidbutgetParameters,updateParameters,duplicateParameters, anddeleteParametersdon't annotate their UUID parameters. Consider applying@NonNullconsistently for uniform null-safety contracts.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/DynamicSimulationClient.java` around lines 31 - 45, The UUID parameter null-safety is inconsistent: add `@NonNull` to the UUID parameters of getParameters(UUID), updateParameters(UUID,...), duplicateParameters(UUID) and deleteParameters(UUID) so their signatures match getProvider(`@NonNull` UUID) and enforce a uniform contract; keep existing annotations on createParameters(String) and leave userId as-is unless you want it non-null too.src/test/java/org/gridsuite/study/server/StudyControllerDynamicSimulationTest.java (1)
104-105: Use a real JSON payload and verify it is forwarded unchanged.This endpoint now persists raw JSON strings. With
PARAMETERS_JSON = "parametersJson"andcreateParameters(any()), the test does not exercise the real payload shape and won’t catch body mangling on the controller path.🧪 Strengthen the round-trip assertion
- private static final String PARAMETERS_JSON = "parametersJson"; + private static final String PARAMETERS_JSON = "{\"startTime\":0,\"stopTime\":500}"; @@ - doAnswer(invocation -> PARAMETERS_UUID) - .when(spyDynamicSimulationService).createParameters(any()); + doAnswer(invocation -> PARAMETERS_UUID) + .when(spyDynamicSimulationService).createParameters(eq(jsonParameters)); @@ studyClient.perform(post(STUDY_BASE_URL + DELIMITER + STUDY_DYNAMIC_SIMULATION_END_POINT_PARAMETERS, studyUuid) .header(HEADER_USER_ID_NAME, HEADER_USER_ID_VALUE) .contentType(MediaType.APPLICATION_JSON) .content(jsonParameters)) .andExpect(status().isOk()).andReturn(); + verify(spyDynamicSimulationService).createParameters(eq(jsonParameters));Also applies to: 693-706
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/test/java/org/gridsuite/study/server/StudyControllerDynamicSimulationTest.java` around lines 104 - 105, Replace the placeholder PARAMETERS_JSON usage and the generic createParameters(any()) stub in StudyControllerDynamicSimulationTest with a real JSON string (e.g. a small nested object/array) and use that exact string in the request; then capture the argument passed to the mocked createParameters (via ArgumentCaptor or Mockito.verify) and assert the captured value equals the original JSON string so the controller forwards the raw body unchanged (reference PARAMETERS_JSON, createParameters(...), and the test method in StudyControllerDynamicSimulationTest).src/main/java/org/gridsuite/study/server/controller/StudyController.java (1)
1834-1837: Add explicit JSON media type to DS parameters GET endpoint.The endpoint returns
ResponseEntity<String>without explicitproducesdeclaration, allowing content-type negotiation to default to plain text. PinningMediaType.APPLICATION_JSON_VALUEensures client-side content-type safety and aligns with similar endpoints in the controller that already declare explicit media types.Note: Similar parameter GET endpoints across the controller (voltage-init, loadflow, dynamic-security-analysis, security-analysis, etc.) also lack explicit media-type declarations—consider a broader pass to standardize this pattern.
♻️ Proposed change
- `@GetMapping`(value = "/studies/{studyUuid}/dynamic-simulation/parameters") + `@GetMapping`(value = "/studies/{studyUuid}/dynamic-simulation/parameters", produces = MediaType.APPLICATION_JSON_VALUE) `@Operation`(summary = "Get dynamic simulation parameters on study") `@ApiResponses`(value = {`@ApiResponse`(responseCode = "200", description = "The dynamic simulation parameters")}) public ResponseEntity<String> getDynamicSimulationParameters( `@PathVariable`("studyUuid") UUID studyUuid, `@RequestHeader`(HEADER_USER_ID) String userId) { - return ResponseEntity.ok().body(studyService.getDynamicSimulationParameters(studyUuid, userId)); + return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON) + .body(studyService.getDynamicSimulationParameters(studyUuid, userId)); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/org/gridsuite/study/server/controller/StudyController.java` around lines 1834 - 1837, The GET endpoint method getDynamicSimulationParameters currently returns ResponseEntity<String> without an explicit produces media type; update its mapping annotation (the `@GetMapping/`@RequestMapping for getDynamicSimulationParameters) to include produces = MediaType.APPLICATION_JSON_VALUE so the response Content-Type is pinned to application/json and matches other parameter endpoints; apply the same pattern for other parameter GET endpoints (e.g., voltage-init, loadflow, dynamic-security-analysis, security-analysis) as a follow-up pass to standardize content negotiation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/main/java/org/gridsuite/study/server/service/StudyService.java`:
- Around line 3006-3018: Replace the direct call to
studyEntity.getDynamicSimulationParametersUuid() used as an argument to
dynamicSimulationService.runDynamicSimulation with the defensive helper to
guarantee a non-null UUID: call
getDynamicSimulationParametersUuidOrElseCreateDefault(studyEntity) and pass its
result into runDynamicSimulation; update the reference near where
dynamicSimulationResultUuid is created so runDynamicSimulation receives the
non-null UUID instead of the raw
studyEntity.getDynamicSimulationParametersUuid() value.
In
`@src/test/java/org/gridsuite/study/server/service/client/dynamicsimulation/DynamicSimulationClientTest.java`:
- Around line 127-157: Update the WireMock stubs in DynamicSimulationClientTest
so they assert the forwarded HEADER_USER_ID header is present and equals the
expected value; specifically, for each
wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo(url)) ...) (the stubs
used for the success, not-found, and server-error cases) add a header matcher
that checks HEADER_USER_ID equals "userId" (or the test's userId variable) so
the stubs only match when DynamicSimulationClientImpl.getParameters(...)
actually forwards the header.
- Around line 316-352: The test's error path is a false positive because the
WireMock error stub incorrectly uses withHeader(QUERY_PARAM_DEBUG, ...) instead
of withQueryParam(QUERY_PARAM_DEBUG, ...) and doesn't verify the request body
(`events`), so WireMock falls back to 404; update both error stubs to use
withQueryParam("debug", equalTo("true")) (matching the real client behavior) and
add a request body matcher that verifies `events` (e.g.
withRequestBody(equalToJson(objectMapper.writeValueAsString(events)))); finally
change the asserted exception from HttpClientErrorException.NotFound.class to
HttpServerErrorException.class when calling dynamicSimulationClient.run(...) so
the test expects the 500 server error.
---
Outside diff comments:
In
`@src/main/java/org/gridsuite/study/server/service/client/dynamicmargincalculation/DynamicMarginCalculationClient.java`:
- Around line 154-162: The method run in DynamicMarginCalculationClient is
missing a null-check for the `@NonNull` parameter dynamicSimulationParametersUuid;
add an Objects.requireNonNull(dynamicSimulationParametersUuid) call in the same
validation block where receiver, networkUuid, reportInfos,
dynamicSecurityAnalysisParametersUuid, and parametersUuid are checked so the
method consistently validates all `@NonNull` parameters and throws a clear NPE if
dynamicSimulationParametersUuid is null.
In
`@src/test/java/org/gridsuite/study/server/service/client/dynamicmargincalculation/DynamicMarginCalculationClientTest.java`:
- Around line 306-321: The WireMock stub in DynamicMarginCalculationClientTest
is missing validation for the dynamicSimulationParametersUuid query parameter;
update the stub chain (the WireMock.post(...).withQueryParam(...) calls) to
include .withQueryParam("dynamicSimulationParametersUuid",
equalTo(DYNAMIC_SIMULATION_PARAMETERS_UUID.toString())) so the stub matches the
production call made by dynamicMarginCalculationClient.run and uses the existing
DYNAMIC_SIMULATION_PARAMETERS_UUID test constant.
- Around line 327-345: The WireMock error stub in
DynamicMarginCalculationClientTest is missing validation for the
dynamicSimulationParametersUuid query param; update the stub configured via
wireMockServer.stubFor(...) (same block that uses url, QUERY_PARAM_VARIANT_ID,
QUERY_PARAM_RECEIVER, etc.) to include
.withQueryParam("dynamicSimulationParametersUuid",
equalTo(DYNAMIC_SIMULATION_PARAMETERS_UUID.toString())) so the error case
validates the dynamicSimulationParametersUuid the same way the success case
does.
---
Nitpick comments:
In `@src/main/java/org/gridsuite/study/server/controller/StudyController.java`:
- Around line 1834-1837: The GET endpoint method getDynamicSimulationParameters
currently returns ResponseEntity<String> without an explicit produces media
type; update its mapping annotation (the `@GetMapping/`@RequestMapping for
getDynamicSimulationParameters) to include produces =
MediaType.APPLICATION_JSON_VALUE so the response Content-Type is pinned to
application/json and matches other parameter endpoints; apply the same pattern
for other parameter GET endpoints (e.g., voltage-init, loadflow,
dynamic-security-analysis, security-analysis) as a follow-up pass to standardize
content negotiation.
In
`@src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/DynamicSimulationClient.java`:
- Around line 31-45: The UUID parameter null-safety is inconsistent: add
`@NonNull` to the UUID parameters of getParameters(UUID),
updateParameters(UUID,...), duplicateParameters(UUID) and deleteParameters(UUID)
so their signatures match getProvider(`@NonNull` UUID) and enforce a uniform
contract; keep existing annotations on createParameters(String) and leave userId
as-is unless you want it non-null too.
In `@src/main/resources/db/changelog/changesets/changelog_20260319T184344Z.xml`:
- Around line 6-7: The XML changeset has inconsistent tableName casing: some
tags use tableName="study" and others tableName="STUDY"; update all tableName
attributes in this changeset to use a single consistent casing (pick one
convention—prefer lowercase "study") for every change element (e.g., the
<addColumn tableName="study"> and the other change elements referencing STUDY)
so all occurrences match exactly for readability and consistency.
In
`@src/test/java/org/gridsuite/study/server/StudyControllerDynamicSimulationTest.java`:
- Around line 104-105: Replace the placeholder PARAMETERS_JSON usage and the
generic createParameters(any()) stub in StudyControllerDynamicSimulationTest
with a real JSON string (e.g. a small nested object/array) and use that exact
string in the request; then capture the argument passed to the mocked
createParameters (via ArgumentCaptor or Mockito.verify) and assert the captured
value equals the original JSON string so the controller forwards the raw body
unchanged (reference PARAMETERS_JSON, createParameters(...), and the test method
in StudyControllerDynamicSimulationTest).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7c70644d-b3cf-4168-8cd8-2d1ec27f4338
📒 Files selected for processing (44)
src/main/java/org/gridsuite/study/server/controller/StudyController.javasrc/main/java/org/gridsuite/study/server/dto/UserProfileInfos.javasrc/main/java/org/gridsuite/study/server/dto/dynamicsimulation/DynamicSimulationParametersInfos.javasrc/main/java/org/gridsuite/study/server/dto/dynamicsimulation/curve/CurveInfos.javasrc/main/java/org/gridsuite/study/server/dto/dynamicsimulation/network/NetworkInfos.javasrc/main/java/org/gridsuite/study/server/dto/dynamicsimulation/solver/AbstractSolverInfos.javasrc/main/java/org/gridsuite/study/server/dto/dynamicsimulation/solver/IdaSolverInfos.javasrc/main/java/org/gridsuite/study/server/dto/dynamicsimulation/solver/SimSolverInfos.javasrc/main/java/org/gridsuite/study/server/dto/dynamicsimulation/solver/SolverInfos.javasrc/main/java/org/gridsuite/study/server/dto/dynamicsimulation/solver/SolverTypeInfos.javasrc/main/java/org/gridsuite/study/server/repository/DynamicSimulationParametersEntity.javasrc/main/java/org/gridsuite/study/server/repository/StudyEntity.javasrc/main/java/org/gridsuite/study/server/service/ConsumerService.javasrc/main/java/org/gridsuite/study/server/service/FilterService.javasrc/main/java/org/gridsuite/study/server/service/StudyService.javasrc/main/java/org/gridsuite/study/server/service/client/RestClient.javasrc/main/java/org/gridsuite/study/server/service/client/dynamicmapping/impl/DynamicMappingClientImpl.javasrc/main/java/org/gridsuite/study/server/service/client/dynamicmargincalculation/DynamicMarginCalculationClient.javasrc/main/java/org/gridsuite/study/server/service/client/dynamicsecurityanalysis/DynamicSecurityAnalysisClient.javasrc/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/DynamicSimulationClient.javasrc/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/impl/DynamicSimulationClientImpl.javasrc/main/java/org/gridsuite/study/server/service/client/timeseries/impl/TimeSeriesClientImpl.javasrc/main/java/org/gridsuite/study/server/service/dynamicmargincalculation/DynamicMarginCalculationService.javasrc/main/java/org/gridsuite/study/server/service/dynamicsecurityanalysis/DynamicSecurityAnalysisService.javasrc/main/java/org/gridsuite/study/server/service/dynamicsimulation/DynamicSimulationService.javasrc/main/java/org/gridsuite/study/server/service/dynamicsimulation/impl/DynamicSimulationServiceImpl.javasrc/main/resources/db/changelog/changesets/changelog_20260319T184344Z.xmlsrc/main/resources/db/changelog/db.changelog-master.yamlsrc/test/java/org/gridsuite/study/server/StudyControllerDynamicMarginCalculationTest.javasrc/test/java/org/gridsuite/study/server/StudyControllerDynamicSecurityAnalysisTest.javasrc/test/java/org/gridsuite/study/server/StudyControllerDynamicSimulationTest.javasrc/test/java/org/gridsuite/study/server/dto/dynamicsimulation/curve/CurveInfosTest.javasrc/test/java/org/gridsuite/study/server/dto/dynamicsimulation/network/NetworkInfosTest.javasrc/test/java/org/gridsuite/study/server/dto/dynamicsimulation/solver/SolverInfosTest.javasrc/test/java/org/gridsuite/study/server/service/StudyServiceDynamicSimulationTest.javasrc/test/java/org/gridsuite/study/server/service/client/dynamicmargincalculation/DynamicMarginCalculationClientTest.javasrc/test/java/org/gridsuite/study/server/service/client/dynamicsecurityanalysis/DynamicSecurityAnalysisClientTest.javasrc/test/java/org/gridsuite/study/server/service/client/dynamicsimulation/DynamicSimulationClientTest.javasrc/test/java/org/gridsuite/study/server/service/client/dynamicsimulation/ParameterTestUtils.javasrc/test/java/org/gridsuite/study/server/service/dynamicmargincalculation/DynamicMarginCalculationServiceTest.javasrc/test/java/org/gridsuite/study/server/service/dynamicsecurityanalysis/DynamicSecurityAnalysisServiceTest.javasrc/test/java/org/gridsuite/study/server/service/dynamicsimulation/DynamicSimulationServiceTest.javasrc/test/java/org/gridsuite/study/server/studycontroller/StudyTest.javasrc/test/java/org/gridsuite/study/server/studycontroller/StudyTestBase.java
💤 Files with no reviewable changes (12)
- src/test/java/org/gridsuite/study/server/dto/dynamicsimulation/curve/CurveInfosTest.java
- src/main/java/org/gridsuite/study/server/dto/dynamicsimulation/solver/SolverTypeInfos.java
- src/test/java/org/gridsuite/study/server/dto/dynamicsimulation/network/NetworkInfosTest.java
- src/test/java/org/gridsuite/study/server/dto/dynamicsimulation/solver/SolverInfosTest.java
- src/main/java/org/gridsuite/study/server/dto/dynamicsimulation/curve/CurveInfos.java
- src/main/java/org/gridsuite/study/server/dto/dynamicsimulation/solver/AbstractSolverInfos.java
- src/main/java/org/gridsuite/study/server/dto/dynamicsimulation/solver/IdaSolverInfos.java
- src/main/java/org/gridsuite/study/server/dto/dynamicsimulation/solver/SolverInfos.java
- src/main/java/org/gridsuite/study/server/repository/DynamicSimulationParametersEntity.java
- src/main/java/org/gridsuite/study/server/dto/dynamicsimulation/solver/SimSolverInfos.java
- src/main/java/org/gridsuite/study/server/dto/dynamicsimulation/DynamicSimulationParametersInfos.java
- src/main/java/org/gridsuite/study/server/dto/dynamicsimulation/network/NetworkInfos.java
| // get dynamic simulation result uuid | ||
| UUID dynamicSimulationParametersUuid = studyEntity.getDynamicSimulationParametersUuid(); | ||
|
|
||
| // load configured events persisted in the study server DB | ||
| List<EventInfos> events = dynamicSimulationEventService.getEventsByNodeId(nodeUuid); | ||
|
|
||
| // override configured parameters by provided parameters (only provided fields) | ||
| DynamicSimulationParametersInfos mergeParameters = new DynamicSimulationParametersInfos(); | ||
| // attach events to the merged parameters | ||
| mergeParameters.setEvents(events); | ||
|
|
||
| if (configuredParameters != null) { | ||
| PropertyUtils.copyNonNullProperties(configuredParameters, mergeParameters); | ||
| } | ||
| if (parameters != null) { | ||
| PropertyUtils.copyNonNullProperties(parameters, mergeParameters); | ||
| } | ||
| UUID reportUuid = networkModificationTreeService.getComputationReports(nodeUuid, rootNetworkUuid).getOrDefault(DYNAMIC_SIMULATION.name(), UUID.randomUUID()); | ||
| networkModificationTreeService.updateComputationReportUuid(nodeUuid, rootNetworkUuid, DYNAMIC_SIMULATION, reportUuid); | ||
|
|
||
| // launch dynamic simulation | ||
| UUID networkUuid = rootNetworkService.getNetworkUuid(rootNetworkUuid); | ||
| String variantId = networkModificationTreeService.getVariantId(nodeUuid, rootNetworkUuid); | ||
| UUID dynamicSimulationResultUuid = dynamicSimulationService.runDynamicSimulation(studyEntity.getDynamicSimulationProvider(), | ||
| nodeUuid, rootNetworkUuid, networkUuid, variantId, reportUuid, mergeParameters, userId, debug); | ||
| UUID dynamicSimulationResultUuid = dynamicSimulationService.runDynamicSimulation(nodeUuid, rootNetworkUuid, networkUuid, variantId, reportUuid, dynamicSimulationParametersUuid, events, userId, debug); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify how null parametersUuid is handled in DynamicSimulationService.runDynamicSimulation
ast-grep --pattern $'runDynamicSimulation($$$) {
$$$
}'
# Check if there are null checks or default creation in the service
rg -n -A 10 "runDynamicSimulation" --type java -g '*DynamicSimulationService*.java'Repository: gridsuite/study-server
Length of output: 5191
🏁 Script executed:
#!/bin/bash
# Get the full implementation of runDynamicSimulation
sed -n '114,200p' src/main/java/org/gridsuite/study/server/service/dynamicsimulation/impl/DynamicSimulationServiceImpl.java
# Also search for any null checks on parametersUuid
rg -n "parametersUuid" --type java -A 5 -B 5 src/main/java/org/gridsuite/study/server/service/dynamicsimulation/Repository: gridsuite/study-server
Length of output: 19174
Use defensive pattern for dynamic simulation parameters UUID.
studyEntity.getDynamicSimulationParametersUuid() is passed directly to runDynamicSimulation without null handling. Replace with getDynamicSimulationParametersUuidOrElseCreateDefault(studyEntity) (lines 105-110 of DynamicSimulationServiceImpl) to ensure a non-null UUID is passed, matching the defensive pattern used elsewhere in the codebase.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/java/org/gridsuite/study/server/service/StudyService.java` around
lines 3006 - 3018, Replace the direct call to
studyEntity.getDynamicSimulationParametersUuid() used as an argument to
dynamicSimulationService.runDynamicSimulation with the defensive helper to
guarantee a non-null UUID: call
getDynamicSimulationParametersUuidOrElseCreateDefault(studyEntity) and pass its
result into runDynamicSimulation; update the reference near where
dynamicSimulationResultUuid is created so runDynamicSimulation receives the
non-null UUID instead of the raw
studyEntity.getDynamicSimulationParametersUuid() value.
| wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo(url)) | ||
| .willReturn(WireMock.ok() | ||
| .withBody(parametersJson) | ||
| .withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) | ||
| )); | ||
| // call service to test | ||
| String resultParametersJson = dynamicSimulationClient.getParameters(PARAMETERS_UUID, "userId"); | ||
|
|
||
| // check result | ||
| assertThat(resultParametersJson).isEqualTo(parametersJson); | ||
|
|
||
| // --- Not Found --- // | ||
| // configure mock server response | ||
| wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo(url)) | ||
| .willReturn(WireMock.notFound())); | ||
|
|
||
| // check result | ||
| assertThrows( | ||
| HttpClientErrorException.NotFound.class, | ||
| () -> dynamicSimulationClient.getParameters(PARAMETERS_UUID, "userId") | ||
| ); | ||
|
|
||
| // --- Error --- // | ||
| wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo(url)) | ||
| .willReturn(WireMock.serverError())); | ||
|
|
||
| // check result | ||
| assertThrows( | ||
| HttpServerErrorException.class, | ||
| () -> dynamicSimulationClient.getParameters(PARAMETERS_UUID, "userId") | ||
| ); |
There was a problem hiding this comment.
Assert the forwarded userId header in this test.
DynamicSimulationClientImpl.getParameters(...) now conditionally sends HEADER_USER_ID, but these stubs match even when that header is missing. If header forwarding regresses, all three branches still stay green.
🔧 Tighten the WireMock expectations
- wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo(url))
+ wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo(url))
+ .withHeader(HEADER_USER_ID, equalTo("userId"))
.willReturn(WireMock.ok()
.withBody(parametersJson)
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
));
@@
- wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo(url))
+ wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo(url))
+ .withHeader(HEADER_USER_ID, equalTo("userId"))
.willReturn(WireMock.notFound()));
@@
- wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo(url))
+ wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo(url))
+ .withHeader(HEADER_USER_ID, equalTo("userId"))
.willReturn(WireMock.serverError()));📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo(url)) | |
| .willReturn(WireMock.ok() | |
| .withBody(parametersJson) | |
| .withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) | |
| )); | |
| // call service to test | |
| String resultParametersJson = dynamicSimulationClient.getParameters(PARAMETERS_UUID, "userId"); | |
| // check result | |
| assertThat(resultParametersJson).isEqualTo(parametersJson); | |
| // --- Not Found --- // | |
| // configure mock server response | |
| wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo(url)) | |
| .willReturn(WireMock.notFound())); | |
| // check result | |
| assertThrows( | |
| HttpClientErrorException.NotFound.class, | |
| () -> dynamicSimulationClient.getParameters(PARAMETERS_UUID, "userId") | |
| ); | |
| // --- Error --- // | |
| wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo(url)) | |
| .willReturn(WireMock.serverError())); | |
| // check result | |
| assertThrows( | |
| HttpServerErrorException.class, | |
| () -> dynamicSimulationClient.getParameters(PARAMETERS_UUID, "userId") | |
| ); | |
| wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo(url)) | |
| .withHeader(HEADER_USER_ID, equalTo("userId")) | |
| .willReturn(WireMock.ok() | |
| .withBody(parametersJson) | |
| .withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) | |
| )); | |
| // call service to test | |
| String resultParametersJson = dynamicSimulationClient.getParameters(PARAMETERS_UUID, "userId"); | |
| // check result | |
| assertThat(resultParametersJson).isEqualTo(parametersJson); | |
| // --- Not Found --- // | |
| // configure mock server response | |
| wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo(url)) | |
| .withHeader(HEADER_USER_ID, equalTo("userId")) | |
| .willReturn(WireMock.notFound())); | |
| // check result | |
| assertThrows( | |
| HttpClientErrorException.NotFound.class, | |
| () -> dynamicSimulationClient.getParameters(PARAMETERS_UUID, "userId") | |
| ); | |
| // --- Error --- // | |
| wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo(url)) | |
| .withHeader(HEADER_USER_ID, equalTo("userId")) | |
| .willReturn(WireMock.serverError())); | |
| // check result | |
| assertThrows( | |
| HttpServerErrorException.class, | |
| () -> dynamicSimulationClient.getParameters(PARAMETERS_UUID, "userId") | |
| ); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/test/java/org/gridsuite/study/server/service/client/dynamicsimulation/DynamicSimulationClientTest.java`
around lines 127 - 157, Update the WireMock stubs in DynamicSimulationClientTest
so they assert the forwarded HEADER_USER_ID header is present and equals the
expected value; specifically, for each
wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo(url)) ...) (the stubs
used for the success, not-found, and server-error cases) add a header matcher
that checks HEADER_USER_ID equals "userId" (or the test's userId variable) so
the stubs only match when DynamicSimulationClientImpl.getParameters(...)
actually forwards the header.
| wireMockServer.stubFor(WireMock.post(WireMock.urlPathTemplate(url)) | ||
| .withQueryParam(QUERY_PARAM_VARIANT_ID, equalTo(VARIANT_ID)) | ||
| .withQueryParam("provider", equalTo(DYNAWO_PROVIDER)) | ||
| .withQueryParam(QUERY_PARAM_RECEIVER, equalTo("receiver")) | ||
| .withQueryParam(QUERY_PARAM_REPORT_UUID, equalTo(REPORT_UUID.toString())) | ||
| .withQueryParam(QUERY_PARAM_REPORTER_ID, equalTo(NODE_UUID.toString())) | ||
| .withQueryParam(QUERY_PARAM_REPORT_TYPE, equalTo(StudyService.ReportType.DYNAMIC_SIMULATION.reportKey)) | ||
| .withQueryParam("parametersUuid", equalTo(PARAMETERS_UUID.toString())) | ||
| .withHeader(HEADER_USER_ID, equalTo("userId")) | ||
| .willReturn(WireMock.ok() | ||
| .withBody(objectMapper.writeValueAsString(RESULT_UUID)) | ||
| .withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) | ||
| )); | ||
|
|
||
| // call service to test | ||
| UUID resultUuid = dynamicSimulationClient.run(DYNAWO_PROVIDER, "receiver", NETWORK_UUID, VARIANT_ID, | ||
| new ReportInfos(REPORT_UUID, NODE_UUID), parameters, "userId", false); | ||
| UUID resultUuid = dynamicSimulationClient.run("receiver", NETWORK_UUID, VARIANT_ID, | ||
| new ReportInfos(REPORT_UUID, NODE_UUID), PARAMETERS_UUID, events, "userId", false); | ||
|
|
||
| // check result | ||
| assertThat(resultUuid).isEqualTo(RESULT_UUID); | ||
|
|
||
| // --- Error --- // | ||
| wireMockServer.stubFor(WireMock.post(WireMock.urlPathTemplate(url)) | ||
| .withQueryParam(QUERY_PARAM_VARIANT_ID, equalTo("variantIdFailed")) | ||
| .withQueryParam("provider", equalTo("Dynawo")) | ||
| .withQueryParam(QUERY_PARAM_RECEIVER, equalTo("receiver")) | ||
| .withQueryParam(QUERY_PARAM_REPORT_UUID, equalTo(REPORT_UUID.toString())) | ||
| .withQueryParam(QUERY_PARAM_REPORTER_ID, equalTo(NODE_UUID.toString())) | ||
| .withQueryParam(QUERY_PARAM_REPORT_TYPE, equalTo(StudyService.ReportType.DYNAMIC_SIMULATION.reportKey)) | ||
| .withHeader(QUERY_PARAM_DEBUG, equalTo("true")) | ||
| .withQueryParam("parametersUuid", equalTo(PARAMETERS_UUID.toString())) | ||
| .withHeader(HEADER_USER_ID, equalTo("userId")) | ||
| .willReturn(WireMock.serverError())); | ||
|
|
||
| // check result | ||
| assertThrows( | ||
| HttpClientErrorException.NotFound.class, | ||
| () -> dynamicSimulationClient.run("Dynawo", "receiver", NETWORK_UUID, "variantIdFailed", | ||
| new ReportInfos(REPORT_UUID, NODE_UUID), parameters, "userId", true) | ||
| () -> dynamicSimulationClient.run("receiver", NETWORK_UUID, "variantIdFailed", | ||
| new ReportInfos(REPORT_UUID, NODE_UUID), PARAMETERS_UUID, events, "userId", true) | ||
| ); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Implementation contract:"
rg -n -C2 'queryParam\(QUERY_PARAM_DEBUG|HttpEntity<List<EventInfos>>|postForObject' \
src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/impl/DynamicSimulationClientImpl.java
echo
echo "Current test matchers:"
rg -n -C2 'testRun\(|withHeader\(QUERY_PARAM_DEBUG|withQueryParam\(QUERY_PARAM_DEBUG|withRequestBody' \
src/test/java/org/gridsuite/study/server/service/client/dynamicsimulation/DynamicSimulationClientTest.javaRepository: gridsuite/study-server
Length of output: 2874
Fix the run error path—test is a false positive.
The implementation sends debug as a query parameter and events as the request body, but the error stub checks debug as a header and ignores the body. WireMock's fallback 404 satisfies the test instead of the intended 500 path. Additionally, the exception type is incorrect: HttpServerErrorException.class not HttpClientErrorException.NotFound.class.
Apply these fixes to both stubs
wireMockServer.stubFor(WireMock.post(WireMock.urlPathTemplate(url))
+ .withRequestBody(WireMock.equalToJson(objectMapper.writeValueAsString(events)))
.withQueryParam(QUERY_PARAM_VARIANT_ID, equalTo(VARIANT_ID))
.withQueryParam(QUERY_PARAM_RECEIVER, equalTo("receiver"))
.withQueryParam(QUERY_PARAM_REPORT_UUID, equalTo(REPORT_UUID.toString()))
.withQueryParam(QUERY_PARAM_REPORTER_ID, equalTo(NODE_UUID.toString()))
.withQueryParam(QUERY_PARAM_REPORT_TYPE, equalTo(StudyService.ReportType.DYNAMIC_SIMULATION.reportKey))
.withQueryParam("parametersUuid", equalTo(PARAMETERS_UUID.toString()))
.withHeader(HEADER_USER_ID, equalTo("userId"))
.willReturn(WireMock.ok()
.withBody(objectMapper.writeValueAsString(RESULT_UUID))
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
));
wireMockServer.stubFor(WireMock.post(WireMock.urlPathTemplate(url))
.withQueryParam(QUERY_PARAM_VARIANT_ID, equalTo("variantIdFailed"))
.withQueryParam(QUERY_PARAM_RECEIVER, equalTo("receiver"))
.withQueryParam(QUERY_PARAM_REPORT_UUID, equalTo(REPORT_UUID.toString()))
.withQueryParam(QUERY_PARAM_REPORTER_ID, equalTo(NODE_UUID.toString()))
.withQueryParam(QUERY_PARAM_REPORT_TYPE, equalTo(StudyService.ReportType.DYNAMIC_SIMULATION.reportKey))
- .withHeader(QUERY_PARAM_DEBUG, equalTo("true"))
+ .withQueryParam(QUERY_PARAM_DEBUG, equalTo("true"))
+ .withRequestBody(WireMock.equalToJson(objectMapper.writeValueAsString(events)))
.withQueryParam("parametersUuid", equalTo(PARAMETERS_UUID.toString()))
.withHeader(HEADER_USER_ID, equalTo("userId"))
.willReturn(WireMock.serverError()));
- assertThrows(
- HttpClientErrorException.NotFound.class,
+ assertThrows(
+ HttpServerErrorException.class,
() -> dynamicSimulationClient.run("receiver", NETWORK_UUID, "variantIdFailed",
new ReportInfos(REPORT_UUID, NODE_UUID), PARAMETERS_UUID, events, "userId", true)
);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| wireMockServer.stubFor(WireMock.post(WireMock.urlPathTemplate(url)) | |
| .withQueryParam(QUERY_PARAM_VARIANT_ID, equalTo(VARIANT_ID)) | |
| .withQueryParam("provider", equalTo(DYNAWO_PROVIDER)) | |
| .withQueryParam(QUERY_PARAM_RECEIVER, equalTo("receiver")) | |
| .withQueryParam(QUERY_PARAM_REPORT_UUID, equalTo(REPORT_UUID.toString())) | |
| .withQueryParam(QUERY_PARAM_REPORTER_ID, equalTo(NODE_UUID.toString())) | |
| .withQueryParam(QUERY_PARAM_REPORT_TYPE, equalTo(StudyService.ReportType.DYNAMIC_SIMULATION.reportKey)) | |
| .withQueryParam("parametersUuid", equalTo(PARAMETERS_UUID.toString())) | |
| .withHeader(HEADER_USER_ID, equalTo("userId")) | |
| .willReturn(WireMock.ok() | |
| .withBody(objectMapper.writeValueAsString(RESULT_UUID)) | |
| .withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) | |
| )); | |
| // call service to test | |
| UUID resultUuid = dynamicSimulationClient.run(DYNAWO_PROVIDER, "receiver", NETWORK_UUID, VARIANT_ID, | |
| new ReportInfos(REPORT_UUID, NODE_UUID), parameters, "userId", false); | |
| UUID resultUuid = dynamicSimulationClient.run("receiver", NETWORK_UUID, VARIANT_ID, | |
| new ReportInfos(REPORT_UUID, NODE_UUID), PARAMETERS_UUID, events, "userId", false); | |
| // check result | |
| assertThat(resultUuid).isEqualTo(RESULT_UUID); | |
| // --- Error --- // | |
| wireMockServer.stubFor(WireMock.post(WireMock.urlPathTemplate(url)) | |
| .withQueryParam(QUERY_PARAM_VARIANT_ID, equalTo("variantIdFailed")) | |
| .withQueryParam("provider", equalTo("Dynawo")) | |
| .withQueryParam(QUERY_PARAM_RECEIVER, equalTo("receiver")) | |
| .withQueryParam(QUERY_PARAM_REPORT_UUID, equalTo(REPORT_UUID.toString())) | |
| .withQueryParam(QUERY_PARAM_REPORTER_ID, equalTo(NODE_UUID.toString())) | |
| .withQueryParam(QUERY_PARAM_REPORT_TYPE, equalTo(StudyService.ReportType.DYNAMIC_SIMULATION.reportKey)) | |
| .withHeader(QUERY_PARAM_DEBUG, equalTo("true")) | |
| .withQueryParam("parametersUuid", equalTo(PARAMETERS_UUID.toString())) | |
| .withHeader(HEADER_USER_ID, equalTo("userId")) | |
| .willReturn(WireMock.serverError())); | |
| // check result | |
| assertThrows( | |
| HttpClientErrorException.NotFound.class, | |
| () -> dynamicSimulationClient.run("Dynawo", "receiver", NETWORK_UUID, "variantIdFailed", | |
| new ReportInfos(REPORT_UUID, NODE_UUID), parameters, "userId", true) | |
| () -> dynamicSimulationClient.run("receiver", NETWORK_UUID, "variantIdFailed", | |
| new ReportInfos(REPORT_UUID, NODE_UUID), PARAMETERS_UUID, events, "userId", true) | |
| ); | |
| wireMockServer.stubFor(WireMock.post(WireMock.urlPathTemplate(url)) | |
| .withRequestBody(WireMock.equalToJson(objectMapper.writeValueAsString(events))) | |
| .withQueryParam(QUERY_PARAM_VARIANT_ID, equalTo(VARIANT_ID)) | |
| .withQueryParam(QUERY_PARAM_RECEIVER, equalTo("receiver")) | |
| .withQueryParam(QUERY_PARAM_REPORT_UUID, equalTo(REPORT_UUID.toString())) | |
| .withQueryParam(QUERY_PARAM_REPORTER_ID, equalTo(NODE_UUID.toString())) | |
| .withQueryParam(QUERY_PARAM_REPORT_TYPE, equalTo(StudyService.ReportType.DYNAMIC_SIMULATION.reportKey)) | |
| .withQueryParam("parametersUuid", equalTo(PARAMETERS_UUID.toString())) | |
| .withHeader(HEADER_USER_ID, equalTo("userId")) | |
| .willReturn(WireMock.ok() | |
| .withBody(objectMapper.writeValueAsString(RESULT_UUID)) | |
| .withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) | |
| )); | |
| // call service to test | |
| UUID resultUuid = dynamicSimulationClient.run("receiver", NETWORK_UUID, VARIANT_ID, | |
| new ReportInfos(REPORT_UUID, NODE_UUID), PARAMETERS_UUID, events, "userId", false); | |
| // check result | |
| assertThat(resultUuid).isEqualTo(RESULT_UUID); | |
| // --- Error --- // | |
| wireMockServer.stubFor(WireMock.post(WireMock.urlPathTemplate(url)) | |
| .withQueryParam(QUERY_PARAM_VARIANT_ID, equalTo("variantIdFailed")) | |
| .withQueryParam(QUERY_PARAM_RECEIVER, equalTo("receiver")) | |
| .withQueryParam(QUERY_PARAM_REPORT_UUID, equalTo(REPORT_UUID.toString())) | |
| .withQueryParam(QUERY_PARAM_REPORTER_ID, equalTo(NODE_UUID.toString())) | |
| .withQueryParam(QUERY_PARAM_REPORT_TYPE, equalTo(StudyService.ReportType.DYNAMIC_SIMULATION.reportKey)) | |
| .withQueryParam(QUERY_PARAM_DEBUG, equalTo("true")) | |
| .withRequestBody(WireMock.equalToJson(objectMapper.writeValueAsString(events))) | |
| .withQueryParam("parametersUuid", equalTo(PARAMETERS_UUID.toString())) | |
| .withHeader(HEADER_USER_ID, equalTo("userId")) | |
| .willReturn(WireMock.serverError())); | |
| // check result | |
| assertThrows( | |
| HttpServerErrorException.class, | |
| () -> dynamicSimulationClient.run("receiver", NETWORK_UUID, "variantIdFailed", | |
| new ReportInfos(REPORT_UUID, NODE_UUID), PARAMETERS_UUID, events, "userId", true) | |
| ); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/test/java/org/gridsuite/study/server/service/client/dynamicsimulation/DynamicSimulationClientTest.java`
around lines 316 - 352, The test's error path is a false positive because the
WireMock error stub incorrectly uses withHeader(QUERY_PARAM_DEBUG, ...) instead
of withQueryParam(QUERY_PARAM_DEBUG, ...) and doesn't verify the request body
(`events`), so WireMock falls back to 404; update both error stubs to use
withQueryParam("debug", equalTo("true")) (matching the real client behavior) and
add a request body matcher that verifies `events` (e.g.
withRequestBody(equalToJson(objectMapper.writeValueAsString(events)))); finally
change the asserted exception from HttpClientErrorException.NotFound.class to
HttpServerErrorException.class when calling dynamicSimulationClient.run(...) so
the test expects the 500 server error.
Signed-off-by: Thang PHAM <phamthang37@gmail.com>
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/main/java/org/gridsuite/study/server/controller/StudyController.java (1)
1905-1916:⚠️ Potential issue | 🟠 MajorFail fast on stale bodies for
/dynamic-simulation/run.This keeps the same public route, but it no longer consumes per-run parameters. The updated tests still POST a body and pass, which means older callers will silently lose their overrides instead of getting a clear contract error. Either keep backward compatibility for one release or reject non-empty bodies with
400.💡 One way to make the contract break explicit
public ResponseEntity<Void> runDynamicSimulation(`@Parameter`(description = "studyUuid") `@PathVariable`("studyUuid") UUID studyUuid, `@Parameter`(description = "rootNetworkUuid") `@PathVariable`("rootNetworkUuid") UUID rootNetworkUuid, `@Parameter`(description = "nodeUuid") `@PathVariable`("nodeUuid") UUID nodeUuid, `@Parameter`(description = "debug") `@RequestParam`(name = "debug", required = false, defaultValue = "false") boolean debug, + `@RequestBody`(required = false) String deprecatedParameters, `@RequestHeader`(HEADER_USER_ID) String userId) { + if (StringUtils.isNotBlank(deprecatedParameters)) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, + "Dynamic-simulation parameters must be set through the parameters endpoint before running"); + } studyService.assertIsNodeNotReadOnly(nodeUuid); studyService.assertCanRunOnConstructionNode(studyUuid, nodeUuid, List.of(DYNAWO_PROVIDER), studyService::getDynamicSimulationProvider); studyService.runDynamicSimulation(studyUuid, nodeUuid, rootNetworkUuid, userId, debug); return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).build(); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/org/gridsuite/study/server/controller/StudyController.java` around lines 1905 - 1916, The runDynamicSimulation endpoint currently ignores request bodies which lets old callers silently lose overrides; modify the StudyController.runDynamicSimulation method to fail-fast on non-empty bodies by adding a `@RequestBody`(required = false) String body parameter and, at the start of the method, if body != null && !body.isBlank() throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Request body not supported for this endpoint"); keep the existing calls to studyService.assertIsNodeNotReadOnly, assertCanRunOnConstructionNode and studyService.runDynamicSimulation unchanged so callers get a clear 400 when they send a body rather than silently dropping parameters.
🧹 Nitpick comments (1)
src/test/java/org/gridsuite/study/server/StudyControllerDynamicSimulationTest.java (1)
104-105: Use a real JSON fixture in the parameter round-trip test.
"parametersJson"is plain text, not serialized JSON. Because the production path now treats these parameters as JSON payloads, this test won't catch regressions in JSON validation/serialization. Replacing it with an actual JSON object string would make the new contract much better covered.Also applies to: 689-723
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/test/java/org/gridsuite/study/server/StudyControllerDynamicSimulationTest.java` around lines 104 - 105, The test uses the constant PARAMETERS_JSON ("parametersJson") which is plain text rather than a serialized JSON payload, so update the fixture in StudyControllerDynamicSimulationTest to use a real JSON string (e.g., a JSON object with expected fields) for the parameter round-trip assertions; replace occurrences of PARAMETERS_JSON in the test (and the other instances noted around lines 689-723) with a properly escaped JSON object string that matches the production contract, ensuring the test sends/validates the same JSON structure the controller expects.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@src/main/java/org/gridsuite/study/server/service/dynamicsimulation/impl/DynamicSimulationServiceImpl.java`:
- Around line 105-110: The method
getDynamicSimulationParametersUuidOrElseCreateDefault in
DynamicSimulationServiceImpl must not perform a remote create during a read;
remove the call to dynamicSimulationClient.createDefaultParameters from that
getter and make it purely a read (return the UUID or null). Implement a separate
initialization/migration routine (e.g.,
initializeDynamicSimulationParametersIfMissing) that is invoked from
write/upgrade flows (or from StudyService during a controlled migration path)
and runs under a DB transaction or explicit lock to create the remote default
once, persist the returned UUID into the StudyEntity, and handle retry/race
conditions; ensure StudyService.getDynamicSimulationParameters calls the new
transactional initializer when migration is required rather than letting the
getter POST remotely.
---
Outside diff comments:
In `@src/main/java/org/gridsuite/study/server/controller/StudyController.java`:
- Around line 1905-1916: The runDynamicSimulation endpoint currently ignores
request bodies which lets old callers silently lose overrides; modify the
StudyController.runDynamicSimulation method to fail-fast on non-empty bodies by
adding a `@RequestBody`(required = false) String body parameter and, at the start
of the method, if body != null && !body.isBlank() throw new
ResponseStatusException(HttpStatus.BAD_REQUEST, "Request body not supported for
this endpoint"); keep the existing calls to
studyService.assertIsNodeNotReadOnly, assertCanRunOnConstructionNode and
studyService.runDynamicSimulation unchanged so callers get a clear 400 when they
send a body rather than silently dropping parameters.
---
Nitpick comments:
In
`@src/test/java/org/gridsuite/study/server/StudyControllerDynamicSimulationTest.java`:
- Around line 104-105: The test uses the constant PARAMETERS_JSON
("parametersJson") which is plain text rather than a serialized JSON payload, so
update the fixture in StudyControllerDynamicSimulationTest to use a real JSON
string (e.g., a JSON object with expected fields) for the parameter round-trip
assertions; replace occurrences of PARAMETERS_JSON in the test (and the other
instances noted around lines 689-723) with a properly escaped JSON object string
that matches the production contract, ensuring the test sends/validates the same
JSON structure the controller expects.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ffbbecc6-76be-4e84-bf10-058867204a93
📒 Files selected for processing (10)
src/main/java/org/gridsuite/study/server/controller/StudyController.javasrc/main/java/org/gridsuite/study/server/service/StudyService.javasrc/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/DynamicSimulationClient.javasrc/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/impl/DynamicSimulationClientImpl.javasrc/main/java/org/gridsuite/study/server/service/dynamicsimulation/DynamicSimulationService.javasrc/main/java/org/gridsuite/study/server/service/dynamicsimulation/impl/DynamicSimulationServiceImpl.javasrc/test/java/org/gridsuite/study/server/StudyControllerDynamicSimulationTest.javasrc/test/java/org/gridsuite/study/server/service/StudyServiceDynamicSimulationTest.javasrc/test/java/org/gridsuite/study/server/service/client/dynamicsimulation/DynamicSimulationClientTest.javasrc/test/java/org/gridsuite/study/server/service/dynamicsimulation/DynamicSimulationServiceTest.java
✅ Files skipped from review due to trivial changes (1)
- src/test/java/org/gridsuite/study/server/service/dynamicsimulation/DynamicSimulationServiceTest.java
🚧 Files skipped from review as they are similar to previous changes (3)
- src/test/java/org/gridsuite/study/server/service/StudyServiceDynamicSimulationTest.java
- src/test/java/org/gridsuite/study/server/service/client/dynamicsimulation/DynamicSimulationClientTest.java
- src/main/java/org/gridsuite/study/server/service/StudyService.java
| public UUID getDynamicSimulationParametersUuidOrElseCreateDefault(StudyEntity studyEntity) { | ||
| if (studyEntity.getDynamicSimulationParametersUuid() == null) { | ||
| // not supposed to happen because we create it as the study creation | ||
| studyEntity.setDynamicSimulationParametersUuid(dynamicSimulationClient.createDefaultParameters()); | ||
| } | ||
| return studyEntity.getDynamicSimulationParametersUuid(); |
There was a problem hiding this comment.
Don't lazily create remote default parameters from read paths.
getDynamicSimulationParametersUuidOrElseCreateDefault(...) performs a remote create when the UUID is null. StudyService.getDynamicSimulationParameters(...) already calls this helper from a GET flow (src/main/java/org/gridsuite/study/server/service/StudyService.java:2871-2876), so the first read on an older study now mutates remote state. This is also a check-then-act race: two concurrent requests can each create a default parameter set and only one UUID is retained locally. Please initialize/migrate this UUID once under a transaction/lock instead of opportunistically POSTing here.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/main/java/org/gridsuite/study/server/service/dynamicsimulation/impl/DynamicSimulationServiceImpl.java`
around lines 105 - 110, The method
getDynamicSimulationParametersUuidOrElseCreateDefault in
DynamicSimulationServiceImpl must not perform a remote create during a read;
remove the call to dynamicSimulationClient.createDefaultParameters from that
getter and make it purely a read (return the UUID or null). Implement a separate
initialization/migration routine (e.g.,
initializeDynamicSimulationParametersIfMissing) that is invoked from
write/upgrade flows (or from StudyService during a controlled migration path)
and runs under a DB transaction or explicit lock to create the remote default
once, persist the returned UUID into the StudyEntity, and handle retry/race
conditions; ensure StudyService.getDynamicSimulationParameters calls the new
transactional initializer when migration is required rather than letting the
getter POST remotely.
Signed-off-by: Thang PHAM <phamthang37@gmail.com>
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (2)
src/main/java/org/gridsuite/study/server/service/StudyService.java (2)
3040-3052:⚠️ Potential issue | 🟠 MajorMaterialize the DS parameters UUID before the first run.
This still forwards
studyEntity.getDynamicSimulationParametersUuid()directly torunDynamicSimulation(...), even though the getter path already usesgetDynamicSimulationParametersUuidOrElseCreateDefault(studyEntity). A fresh study can therefore fail on its first DS execution unless the params endpoint has been hit first.Suggested fix
- UUID dynamicSimulationParametersUuid = studyEntity.getDynamicSimulationParametersUuid(); + UUID dynamicSimulationParametersUuid = + dynamicSimulationService.getDynamicSimulationParametersUuidOrElseCreateDefault(studyEntity);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/org/gridsuite/study/server/service/StudyService.java` around lines 3040 - 3052, The code is passing studyEntity.getDynamicSimulationParametersUuid() directly to runDynamicSimulation, which can be null for fresh studies; instead call the routine that ensures a params UUID exists (getDynamicSimulationParametersUuidOrElseCreateDefault) and assign its result to dynamicSimulationParametersUuid before invoking dynamicSimulationService.runDynamicSimulation so the created/returned UUID is materialized and passed in; update the reference in the runDynamicSimulation call (keep variable name dynamicSimulationParametersUuid and callers networkModificationTreeService.getComputationReports, networkModificationTreeService.updateComputationReportUuid, and dynamicSimulationService.runDynamicSimulation unchanged).
3152-3162:⚠️ Potential issue | 🟠 MajorCreate default DSA/DMC parameter UUIDs before launching these jobs.
Both run paths now pass raw
studyEntity.get*ParametersUuid()values downstream, but those fields are still lazily created elsewhere in this class. That means a first DSA/DMC execution can send null UUIDs for required parameter sets on a fresh or duplicated study.Suggested fix
- UUID dynamicSecurityAnalysisParametersUuid = studyEntity.getDynamicSecurityAnalysisParametersUuid(); + UUID dynamicSecurityAnalysisParametersUuid = + dynamicSecurityAnalysisService.getDynamicSecurityAnalysisParametersUuidOrElseCreateDefault(studyEntity);- UUID dynamicSimulationParametersUuid = studyEntity.getDynamicSimulationParametersUuid(); + UUID dynamicSimulationParametersUuid = + dynamicSimulationService.getDynamicSimulationParametersUuidOrElseCreateDefault(studyEntity); - UUID dynamicSecurityAnalysisParametersUuid = studyEntity.getDynamicSecurityAnalysisParametersUuid(); + UUID dynamicSecurityAnalysisParametersUuid = + dynamicSecurityAnalysisService.getDynamicSecurityAnalysisParametersUuidOrElseCreateDefault(studyEntity); - UUID dynamicMarginCalculationParametersUuid = studyEntity.getDynamicMarginCalculationParametersUuid(); + UUID dynamicMarginCalculationParametersUuid = + dynamicMarginCalculationService.getDynamicMarginCalculationParametersUuidOrElseCreateDefault(studyEntity);Also applies to: 3253-3270
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/main/java/org/gridsuite/study/server/controller/StudyController.java`:
- Around line 1849-1854: The controller currently ignores the boolean result
from studyService.setDynamicSimulationParameters and always returns 200; update
StudyController.setDynamicSimulationParameters to use the returned boolean and
follow the pattern used by other setters (e.g., setVoltageInitParameters,
setLoadFlowParameters, setDynamicSecurityAnalysisParameters) so that when
studyService.setDynamicSimulationParameters(studyUuid, dsParameter, userId)
returns true the endpoint returns ResponseEntity.noContent().build() and when
false returns ResponseEntity.ok().build().
- Around line 1857-1862: The GET endpoint returns a raw String which makes the
response contract ambiguous; update the mapping to explicitly declare JSON by
adding produces = MediaType.APPLICATION_JSON_VALUE to the `@GetMapping` on
getDynamicSimulationParameters and import org.springframework.http.MediaType,
ensuring the response Content-Type is application/json while still returning
studyService.getDynamicSimulationParameters(studyUuid) from the
getDynamicSimulationParameters method.
In `@src/main/java/org/gridsuite/study/server/service/StudyService.java`:
- Around line 2913-2925: In setDynamicSimulationParameters, after invalidating
dynamic security analysis, also invalidate dynamic margin calculation and emit
its status change: call
invalidateDynamicMarginCalculationStatusOnAllNodes(studyUuid) and then
notificationService.emitStudyChanged(studyUuid, null, null,
NotificationService.UPDATE_TYPE_DYNAMIC_MARGIN_CALCULATION_STATUS); place these
calls in the setDynamicSimulationParameters method (alongside
invalidateDynamicSecurityAnalysisStatusOnAllNodes and its emit) so any existing
DMC result/status is cleared and its status notification is emitted.
---
Duplicate comments:
In `@src/main/java/org/gridsuite/study/server/service/StudyService.java`:
- Around line 3040-3052: The code is passing
studyEntity.getDynamicSimulationParametersUuid() directly to
runDynamicSimulation, which can be null for fresh studies; instead call the
routine that ensures a params UUID exists
(getDynamicSimulationParametersUuidOrElseCreateDefault) and assign its result to
dynamicSimulationParametersUuid before invoking
dynamicSimulationService.runDynamicSimulation so the created/returned UUID is
materialized and passed in; update the reference in the runDynamicSimulation
call (keep variable name dynamicSimulationParametersUuid and callers
networkModificationTreeService.getComputationReports,
networkModificationTreeService.updateComputationReportUuid, and
dynamicSimulationService.runDynamicSimulation unchanged).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3af2dbb5-0bd2-4883-bcfb-ab26da047af0
📒 Files selected for processing (2)
src/main/java/org/gridsuite/study/server/controller/StudyController.javasrc/main/java/org/gridsuite/study/server/service/StudyService.java
| public ResponseEntity<Void> setDynamicSimulationParameters( | ||
| @PathVariable("studyUuid") UUID studyUuid, | ||
| @RequestBody(required = false) DynamicSimulationParametersInfos dsParameter, | ||
| @RequestBody(required = false) String dsParameter, | ||
| @RequestHeader(HEADER_USER_ID) String userId) { | ||
| studyService.setDynamicSimulationParameters(studyUuid, dsParameter, userId); | ||
| return ResponseEntity.ok().build(); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Dynamic simulation parameter setter declarations/usages:"
rg -n -C2 '\bsetDynamicSimulationParameters\s*\(' --type java
echo
echo "Existing controller branches that map service results to HTTP 200/204:"
rg -n -C2 'ResponseEntity\.noContent\(\)\.build\(\)' src/main/java/org/gridsuite/study/server/controller/StudyController.javaRepository: gridsuite/study-server
Length of output: 15539
Fix inconsistent response codes for setDynamicSimulationParameters.
The service method returns a boolean, but this controller endpoint ignores it and always returns HTTP 200. All other parameter setters in this controller follow the pattern: return 204 No Content when the boolean is true, and 200 OK when false. Update this method to match that convention.
Affected pattern in other setters
// Line 980 (setVoltageInitParameters)
return studyService.setVoltageInitParameters(studyUuid, voltageInitParameters, userId) ? ResponseEntity.noContent().build() : ResponseEntity.ok().build();
// Line 1128 (setLoadFlowParameters)
return studyService.setLoadFlowParameters(studyUuid, lfParameter, userId) ? ResponseEntity.noContent().build() : ResponseEntity.ok().build();
// Line 2009-2011 (setDynamicSecurityAnalysisParameters)
return studyService.setDynamicSecurityAnalysisParameters(studyUuid, dsaParameter, userId) ?
ResponseEntity.noContent().build() :
ResponseEntity.ok().build();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/java/org/gridsuite/study/server/controller/StudyController.java`
around lines 1849 - 1854, The controller currently ignores the boolean result
from studyService.setDynamicSimulationParameters and always returns 200; update
StudyController.setDynamicSimulationParameters to use the returned boolean and
follow the pattern used by other setters (e.g., setVoltageInitParameters,
setLoadFlowParameters, setDynamicSecurityAnalysisParameters) so that when
studyService.setDynamicSimulationParameters(studyUuid, dsParameter, userId)
returns true the endpoint returns ResponseEntity.noContent().build() and when
false returns ResponseEntity.ok().build().
| @GetMapping(value = "/studies/{studyUuid}/dynamic-simulation/parameters") | ||
| @Operation(summary = "Get dynamic simulation parameters on study") | ||
| @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The dynamic simulation parameters")}) | ||
| public ResponseEntity<DynamicSimulationParametersInfos> getDynamicSimulationParameters( | ||
| public ResponseEntity<String> getDynamicSimulationParameters( | ||
| @PathVariable("studyUuid") UUID studyUuid) { | ||
| return ResponseEntity.ok().body(studyService.getDynamicSimulationParameters(studyUuid)); |
There was a problem hiding this comment.
Keep the parameter GET response explicitly JSON.
Once this endpoint returns a raw String instead of a DTO, the JSON response contract is no longer explicit. That can change how clients and generated API docs interpret the same payload.
💡 Suggested fix
- `@GetMapping`(value = "/studies/{studyUuid}/dynamic-simulation/parameters")
+ `@GetMapping`(value = "/studies/{studyUuid}/dynamic-simulation/parameters", produces = MediaType.APPLICATION_JSON_VALUE)
`@Operation`(summary = "Get dynamic simulation parameters on study")
`@ApiResponses`(value = {`@ApiResponse`(responseCode = "200", description = "The dynamic simulation parameters")})
public ResponseEntity<String> getDynamicSimulationParameters(
`@PathVariable`("studyUuid") UUID studyUuid) {
- return ResponseEntity.ok().body(studyService.getDynamicSimulationParameters(studyUuid));
+ return ResponseEntity.ok()
+ .contentType(MediaType.APPLICATION_JSON)
+ .body(studyService.getDynamicSimulationParameters(studyUuid));
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/java/org/gridsuite/study/server/controller/StudyController.java`
around lines 1857 - 1862, The GET endpoint returns a raw String which makes the
response contract ambiguous; update the mapping to explicitly declare JSON by
adding produces = MediaType.APPLICATION_JSON_VALUE to the `@GetMapping` on
getDynamicSimulationParameters and import org.springframework.http.MediaType,
ensuring the response Content-Type is application/json while still returning
studyService.getDynamicSimulationParameters(studyUuid) from the
getDynamicSimulationParameters method.
| public boolean setDynamicSimulationParameters(UUID studyUuid, String dsParameter, String userId) { | ||
| StudyEntity studyEntity = getStudy(studyUuid); | ||
| boolean userProfileIssue = createOrUpdateDynamicSimulationParameters(studyEntity, dsParameter, userId); | ||
| invalidateDynamicSimulationStatusOnAllNodes(studyUuid); | ||
| notificationService.emitStudyChanged(studyUuid, null, null, NotificationService.UPDATE_TYPE_DYNAMIC_SIMULATION_STATUS); | ||
|
|
||
| // Dynamic security analysis depends on dynamic simulation => must invalidate | ||
| invalidateDynamicSecurityAnalysisStatusOnAllNodes(studyUuid); | ||
| notificationService.emitStudyChanged(studyUuid, null, null, NotificationService.UPDATE_TYPE_DYNAMIC_SECURITY_ANALYSIS_STATUS); | ||
|
|
||
| notificationService.emitElementUpdated(studyUuid, userId); | ||
| notificationService.emitComputationParamsChanged(studyUuid, DYNAMIC_SIMULATION); | ||
| return userProfileIssue; |
There was a problem hiding this comment.
Invalidate dynamic margin calculation when DS parameters change.
runDynamicMarginCalculation(...) still consumes dynamicSimulationParametersUuid, so this setter currently leaves any existing DMC result/status stale after a DS parameter update. Invalidate DMC here and emit its status notification too.
Suggested fix
invalidateDynamicSimulationStatusOnAllNodes(studyUuid);
notificationService.emitStudyChanged(studyUuid, null, null, NotificationService.UPDATE_TYPE_DYNAMIC_SIMULATION_STATUS);
// Dynamic security analysis depends on dynamic simulation => must invalidate
invalidateDynamicSecurityAnalysisStatusOnAllNodes(studyUuid);
notificationService.emitStudyChanged(studyUuid, null, null, NotificationService.UPDATE_TYPE_DYNAMIC_SECURITY_ANALYSIS_STATUS);
+
+ // Dynamic margin calculation also depends on dynamic simulation parameters
+ invalidateDynamicMarginCalculationStatusOnAllNodes(studyUuid);
+ notificationService.emitStudyChanged(studyUuid, null, null, NotificationService.UPDATE_TYPE_DYNAMIC_MARGIN_CALCULATION_STATUS);
notificationService.emitElementUpdated(studyUuid, userId);
notificationService.emitComputationParamsChanged(studyUuid, DYNAMIC_SIMULATION);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/java/org/gridsuite/study/server/service/StudyService.java` around
lines 2913 - 2925, In setDynamicSimulationParameters, after invalidating dynamic
security analysis, also invalidate dynamic margin calculation and emit its
status change: call
invalidateDynamicMarginCalculationStatusOnAllNodes(studyUuid) and then
notificationService.emitStudyChanged(studyUuid, null, null,
NotificationService.UPDATE_TYPE_DYNAMIC_MARGIN_CALCULATION_STATUS); place these
calls in the setDynamicSimulationParameters method (alongside
invalidateDynamicSecurityAnalysisStatusOnAllNodes and its emit) so any existing
DMC result/status is cleared and its status notification is emitted.
src/main/java/org/gridsuite/study/server/controller/StudyController.java
Show resolved
Hide resolved
src/main/java/org/gridsuite/study/server/controller/StudyController.java
Show resolved
Hide resolved
src/main/java/org/gridsuite/study/server/controller/StudyController.java
Show resolved
Hide resolved
Signed-off-by: Thang PHAM <phamthang37@gmail.com>
Signed-off-by: Thang PHAM <phamthang37@gmail.com>
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/impl/DynamicSimulationClientImpl.java (1)
153-179:⚠️ Potential issue | 🟠 MajorGuard required run inputs before URL/query construction.
At Line 165 and Lines 167-169,
parametersUuidandreportInfosare used without validation. If either is null, request construction can fail late (or produce an invalid request), which is harder to diagnose.Suggested fix
`@Override` public UUID run(String receiver, UUID networkUuid, String variantId, ReportInfos reportInfos, UUID parametersUuid, List<EventInfos> events, String userId, boolean debug) { Objects.requireNonNull(networkUuid); + Objects.requireNonNull(reportInfos); + Objects.requireNonNull(parametersUuid); String endPointUrl = buildEndPointUrl(getBaseUri(), DYNAMIC_SIMULATION_API_VERSION, DYNAMIC_SIMULATION_END_POINT_RUN); @@ - HttpEntity<List<EventInfos>> httpEntity = new HttpEntity<>(events, headers); + HttpEntity<List<EventInfos>> httpEntity = new HttpEntity<>(events == null ? List.of() : events, headers); return getRestTemplate().postForObject(uriComponent.toUriString(), httpEntity, UUID.class); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/impl/DynamicSimulationClientImpl.java` around lines 153 - 179, In run (DynamicSimulationClientImpl.run) validate required inputs before building the URL: add null checks (e.g., Objects.requireNonNull) for parametersUuid and reportInfos and also ensure reportInfos.reportUuid() and reportInfos.nodeUuid() are non-null (or throw an IllegalArgumentException with a clear message) so URI/queryParam construction won't receive nulls; keep existing checks for networkUuid and receiver as-is and perform these validations at the top of the method before using parametersUuid, reportInfos.reportUuid(), or reportInfos.nodeUuid().
🧹 Nitpick comments (1)
src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/impl/DynamicSimulationClientImpl.java (1)
46-148: Extract oneparametersBaseUrlhelper to reduce duplication.
buildEndPointUrl(getBaseUri(), DYNAMIC_SIMULATION_API_VERSION, DYNAMIC_SIMULATION_END_POINT_PARAMETER)is repeated several times (Lines 47, 60, 83, 117, 140). Centralizing it will make future endpoint/version changes safer.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/impl/DynamicSimulationClientImpl.java` around lines 46 - 148, Extract a private helper method (e.g. getParametersBaseUrl()) that returns buildEndPointUrl(getBaseUri(), DYNAMIC_SIMULATION_API_VERSION, DYNAMIC_SIMULATION_END_POINT_PARAMETER) and replace all local occurrences of parametersBaseUrl in methods like getParametersWithUuidUrl, getProvider, getParameters, createParameters, duplicateParameters, deleteParameters and createDefaultParameters with a call to this helper; update getParametersWithUuidUrl to call getParametersBaseUrl() so the base URL construction is centralized and duplication is removed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@src/main/java/org/gridsuite/study/server/service/client/dynamicmargincalculation/DynamicMarginCalculationClient.java`:
- Around line 153-156: The run(...) method is missing an upfront null check for
the required dynamicSimulationParametersUuid parameter; add a fail-fast
validation at the start of DynamicMarginCalculationClient.run that verifies
dynamicSimulationParametersUuid is not null (e.g., Objects.requireNonNull or
throw new IllegalArgumentException) so you don't build a downstream request with
a missing simulation-parameters UUID; keep the same behavior for the other
already-validated UUIDs and apply the check before the request body construction
where dynamicSimulationParametersUuid is added.
In
`@src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/impl/DynamicSimulationClientImpl.java`:
- Around line 134-135: The inline comment above the REST call in
DynamicSimulationClientImpl incorrectly mentions "dynamic-margin-calculation";
update that comment to reference the correct service ("dynamic-simulation") or
remove the stale comment entirely so it accurately describes the
getRestTemplate().delete(url) call to the dynamic-simulation endpoint (locate
the comment immediately above the getRestTemplate().delete(url) invocation in
DynamicSimulationClientImpl).
---
Outside diff comments:
In
`@src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/impl/DynamicSimulationClientImpl.java`:
- Around line 153-179: In run (DynamicSimulationClientImpl.run) validate
required inputs before building the URL: add null checks (e.g.,
Objects.requireNonNull) for parametersUuid and reportInfos and also ensure
reportInfos.reportUuid() and reportInfos.nodeUuid() are non-null (or throw an
IllegalArgumentException with a clear message) so URI/queryParam construction
won't receive nulls; keep existing checks for networkUuid and receiver as-is and
perform these validations at the top of the method before using parametersUuid,
reportInfos.reportUuid(), or reportInfos.nodeUuid().
---
Nitpick comments:
In
`@src/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/impl/DynamicSimulationClientImpl.java`:
- Around line 46-148: Extract a private helper method (e.g.
getParametersBaseUrl()) that returns buildEndPointUrl(getBaseUri(),
DYNAMIC_SIMULATION_API_VERSION, DYNAMIC_SIMULATION_END_POINT_PARAMETER) and
replace all local occurrences of parametersBaseUrl in methods like
getParametersWithUuidUrl, getProvider, getParameters, createParameters,
duplicateParameters, deleteParameters and createDefaultParameters with a call to
this helper; update getParametersWithUuidUrl to call getParametersBaseUrl() so
the base URL construction is centralized and duplication is removed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e12045e4-04cc-4ae0-b5f0-a065092b8c3a
📒 Files selected for processing (4)
src/main/java/org/gridsuite/study/server/service/client/dynamicmargincalculation/DynamicMarginCalculationClient.javasrc/main/java/org/gridsuite/study/server/service/client/dynamicsecurityanalysis/DynamicSecurityAnalysisClient.javasrc/main/java/org/gridsuite/study/server/service/client/dynamicsimulation/impl/DynamicSimulationClientImpl.javasrc/main/resources/db/changelog/changesets/changelog_20260319T184344Z.xml
✅ Files skipped from review due to trivial changes (1)
- src/main/resources/db/changelog/changesets/changelog_20260319T184344Z.xml
🚧 Files skipped from review as they are similar to previous changes (1)
- src/main/java/org/gridsuite/study/server/service/client/dynamicsecurityanalysis/DynamicSecurityAnalysisClient.java
| public UUID run(@NonNull String receiver, @NonNull UUID networkUuid, String variantId, | ||
| @NonNull ReportInfos reportInfos, @NonNull UUID dynamicSimulationParametersUuid, | ||
| @NonNull UUID dynamicSecurityAnalysisParametersUuid, | ||
| @NonNull UUID parametersUuid, String userId, boolean debug) { |
There was a problem hiding this comment.
Fail fast on the new required simulation-parameters UUID.
dynamicSimulationParametersUuid is mandatory at Line 154 and always added to the request at Line 173, but it is the only required UUID here that is not guarded up front. If a null slips through, this client will build a bad downstream request instead of failing immediately.
Suggested fix
Objects.requireNonNull(receiver);
Objects.requireNonNull(networkUuid);
Objects.requireNonNull(reportInfos);
+ Objects.requireNonNull(dynamicSimulationParametersUuid);
Objects.requireNonNull(dynamicSecurityAnalysisParametersUuid);
Objects.requireNonNull(parametersUuid);Also applies to: 173-173
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/main/java/org/gridsuite/study/server/service/client/dynamicmargincalculation/DynamicMarginCalculationClient.java`
around lines 153 - 156, The run(...) method is missing an upfront null check for
the required dynamicSimulationParametersUuid parameter; add a fail-fast
validation at the start of DynamicMarginCalculationClient.run that verifies
dynamicSimulationParametersUuid is not null (e.g., Objects.requireNonNull or
throw new IllegalArgumentException) so you don't build a downstream request with
a missing simulation-parameters UUID; keep the same behavior for the other
already-validated UUIDs and apply the check before the request body construction
where dynamicSimulationParametersUuid is added.
...ridsuite/study/server/service/client/dynamicsimulation/impl/DynamicSimulationClientImpl.java
Outdated
Show resolved
Hide resolved
...ridsuite/study/server/service/client/dynamicsimulation/impl/DynamicSimulationClientImpl.java
Outdated
Show resolved
Hide resolved
Correct comment
|



PR Summary