This is an automated email from the ASF dual-hosted git repository.
adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new 634814071 FINERACT-2081: Fix "resolve dependent variable" logic of
Batch request resolver
634814071 is described below
commit 6348140716d3b7f3903483d1a383f8e9857ae04b
Author: Adam Saghy <[email protected]>
AuthorDate: Thu Jan 9 20:13:17 2025 +0100
FINERACT-2081: Fix "resolve dependent variable" logic of Batch request
resolver
---
.../fineract/batch/service/ResolutionHelper.java | 43 ++++-----
.../batch/service/ResolutionHelperTest.java | 107 +++++++++++++++++++++
2 files changed, 127 insertions(+), 23 deletions(-)
diff --git
a/fineract-core/src/main/java/org/apache/fineract/batch/service/ResolutionHelper.java
b/fineract-core/src/main/java/org/apache/fineract/batch/service/ResolutionHelper.java
index f27e0afbf..332041706 100644
---
a/fineract-core/src/main/java/org/apache/fineract/batch/service/ResolutionHelper.java
+++
b/fineract-core/src/main/java/org/apache/fineract/batch/service/ResolutionHelper.java
@@ -22,6 +22,7 @@ import com.google.common.base.Splitter;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ReadContext;
import java.util.ArrayList;
@@ -133,7 +134,7 @@ public class ResolutionHelper {
// parameter
for (Map.Entry<String, JsonElement> element :
jsonRequestBody.entrySet()) {
final String key = element.getKey();
- final JsonElement value = resolveDependentVariables(element,
responseCtx);
+ final JsonElement value =
resolveDependentVariables(element.getValue(), responseCtx);
jsonResultBody.add(key, value);
}
// Set the body after dependency resolution
@@ -162,20 +163,19 @@ public class ResolutionHelper {
return request;
}
- private JsonElement resolveDependentVariables(final Map.Entry<String,
JsonElement> entryElement, final ReadContext responseCtx) {
+ private JsonElement resolveDependentVariables(final JsonElement
jsonElement, final ReadContext responseCtx) {
JsonElement value;
- final JsonElement element = entryElement.getValue();
- if (element.isJsonObject()) {
- final JsonObject jsObject = element.getAsJsonObject();
+ if (jsonElement.isJsonObject()) {
+ final JsonObject jsObject = jsonElement.getAsJsonObject();
value = processJsonObject(jsObject, responseCtx);
- } else if (element.isJsonArray()) {
- final JsonArray jsElementArray = element.getAsJsonArray();
+ } else if (jsonElement.isJsonArray()) {
+ final JsonArray jsElementArray = jsonElement.getAsJsonArray();
value = processJsonArray(jsElementArray, responseCtx);
- } else if (element.isJsonNull()) {
+ } else if (jsonElement.isJsonNull()) {
// No further processing of null values
- value = element;
+ value = jsonElement;
} else {
- value = resolveDependentVariable(element, responseCtx);
+ value = processJsonPrimitive(jsonElement, responseCtx);
}
return value;
}
@@ -183,9 +183,7 @@ public class ResolutionHelper {
private JsonElement processJsonObject(final JsonObject jsObject, final
ReadContext responseCtx) {
JsonObject valueObj = new JsonObject();
for (Map.Entry<String, JsonElement> element : jsObject.entrySet()) {
- final String key = element.getKey();
- final JsonElement value =
resolveDependentVariable(element.getValue(), responseCtx);
- valueObj.add(key, value);
+ valueObj.add(element.getKey(),
resolveDependentVariables(element.getValue(), responseCtx));
}
return valueObj;
}
@@ -193,21 +191,20 @@ public class ResolutionHelper {
private JsonArray processJsonArray(final JsonArray elementArray, final
ReadContext responseCtx) {
JsonArray valueArr = new JsonArray();
for (JsonElement element : elementArray) {
- if (element.isJsonObject()) {
- final JsonObject jsObject = element.getAsJsonObject();
- valueArr.add(processJsonObject(jsObject, responseCtx));
- }
+ valueArr.add(resolveDependentVariables(element, responseCtx));
}
return valueArr;
}
- private JsonElement resolveDependentVariable(final JsonElement element,
final ReadContext responseCtx) {
+ private JsonElement processJsonPrimitive(final JsonElement element, final
ReadContext responseCtx) {
JsonElement value = element;
- String paramVal = element.getAsString();
- if (paramVal.contains("$.")) {
- // Get the value of the parameter from parent response
- final String resParamValue = responseCtx.read(paramVal).toString();
- value = this.fromJsonHelper.parse(resParamValue);
+ if (element instanceof JsonPrimitive) {
+ String paramVal = element.getAsString();
+ if (paramVal.contains("$.")) {
+ // Get the value of the parameter from parent response
+ final String resParamValue =
responseCtx.read(paramVal).toString();
+ value = this.fromJsonHelper.parse(resParamValue);
+ }
}
return value;
}
diff --git
a/fineract-core/src/test/java/org/apache/fineract/batch/service/ResolutionHelperTest.java
b/fineract-core/src/test/java/org/apache/fineract/batch/service/ResolutionHelperTest.java
new file mode 100644
index 000000000..1a735b9d6
--- /dev/null
+++
b/fineract-core/src/test/java/org/apache/fineract/batch/service/ResolutionHelperTest.java
@@ -0,0 +1,107 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.batch.service;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.jayway.jsonpath.ReadContext;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.fineract.batch.domain.BatchRequest;
+import org.apache.fineract.batch.domain.BatchResponse;
+import org.apache.fineract.batch.exception.BatchReferenceInvalidException;
+import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
+import org.junit.jupiter.api.Test;
+
+public class ResolutionHelperTest {
+
+ private final FromJsonHelper fromJsonHelper = new FromJsonHelper();
+ private final ResolutionHelper resolutionHelper = new
ResolutionHelper(fromJsonHelper);
+
+ @Test
+ void testBuildNodesTreeWithValidRequests() {
+ List<BatchRequest> requests = new ArrayList<>();
+ BatchRequest firstRequest = new BatchRequest();
+ firstRequest.setRequestId(1L);
+ firstRequest.setBody("{\"key1\": \"value1\", \"key2\": 12, \"key3\":
null, \"key4\": false}");
+ firstRequest.setRelativeUrl("/resource/id");
+ requests.add(firstRequest);
+ BatchRequest secondRequest = new BatchRequest();
+ secondRequest.setRequestId(2L);
+ secondRequest.setReference(1L);
+ secondRequest.setRelativeUrl("/resource/id");
+ secondRequest.setBody("{\"key1\": { \"subKey\": false }, \"key2\":
[1,2,3]}");
+ requests.add(secondRequest);
+ BatchRequest thirdRequest = new BatchRequest();
+ thirdRequest.setRequestId(3L);
+ thirdRequest.setReference(2L);
+ requests.add(thirdRequest);
+ List<ResolutionHelper.BatchRequestNode> nodes =
resolutionHelper.buildNodesTree(requests);
+ assertEquals(1, nodes.size());
+ assertEquals(1, nodes.get(0).getRequest().getRequestId());
+ assertEquals("{\"key1\": \"value1\", \"key2\": 12, \"key3\": null,
\"key4\": false}", nodes.get(0).getRequest().getBody());
+ assertEquals(1, nodes.get(0).getChildNodes().size());
+ assertEquals(2,
nodes.get(0).getChildNodes().get(0).getRequest().getRequestId());
+ assertEquals("{\"key1\": { \"subKey\": false }, \"key2\": [1,2,3]}",
nodes.get(0).getChildNodes().get(0).getRequest().getBody());
+ }
+
+ @Test
+ void testBuildNodesTreeWithInvalidReference() {
+ List<BatchRequest> requests = new ArrayList<>();
+ BatchRequest invalidRequest = new BatchRequest();
+ invalidRequest.setRequestId(2L);
+ // Not existing reference
+ invalidRequest.setReference(1L);
+ requests.add(invalidRequest);
+ assertThrows(BatchReferenceInvalidException.class, () ->
resolutionHelper.buildNodesTree(requests));
+ }
+
+ @Test
+ void testResolveRequestWithValidDependenciesResolveParameterFromResponse()
{
+ BatchRequest batchRequest = new BatchRequest();
+ batchRequest.setBody("{\"key1\": \"$.value1\"}");
+ batchRequest.setRelativeUrl("/resource/$.id?key=value");
+ BatchResponse parentResponse = new BatchResponse();
+ parentResponse.setBody("{\"value1\": \"resolvedValue\", \"id\":
\"123\"}");
+ ReadContext readContext = mock(ReadContext.class);
+ when(readContext.read("$.value1")).thenReturn("resolvedValue");
+ when(readContext.read("$.id")).thenReturn("123");
+ BatchRequest resolvedRequest =
resolutionHelper.resolveRequest(batchRequest, parentResponse);
+ assertNotNull(resolvedRequest);
+ assertEquals("{\"key1\":\"resolvedValue\"}",
resolvedRequest.getBody());
+ assertEquals("/resource/123?key=value",
resolvedRequest.getRelativeUrl());
+ }
+
+ @Test
+ void testResolveRequestWithNoDependencies() {
+ BatchRequest batchRequest = new BatchRequest();
+ batchRequest.setBody("{\"key1\": \"value1\",\"key2\": { \"subKey\":
false }, \"key3\": [1,2,3], \"key4\": null}");
+ batchRequest.setRelativeUrl("/resource/id");
+ BatchResponse parentResponse = new BatchResponse();
+ parentResponse.setBody("{\"value2\": \"not used\"}");
+ BatchRequest resolvedRequest =
resolutionHelper.resolveRequest(batchRequest, parentResponse);
+ assertNotNull(resolvedRequest);
+
assertEquals("{\"key1\":\"value1\",\"key2\":{\"subKey\":false},\"key3\":[1,2,3],\"key4\":null}",
resolvedRequest.getBody());
+ assertEquals("/resource/id", resolvedRequest.getRelativeUrl());
+ }
+}