FINERACT-1724: More batch support for datatables APIs
This commit is contained in:
committed by
Arnold Gálovics
parent
d2082fe2cb
commit
636b33196b
+4
-1
@@ -50,7 +50,7 @@ public class CommandStrategyProvider {
|
||||
/**
|
||||
* Regex pattern for specifying query params
|
||||
*/
|
||||
private static final String MANDATORY_QUERY_PARAM_REGEX = "(\\?(\\w+(?:\\=[\\w,]+|&)+)+)";
|
||||
private static final String MANDATORY_QUERY_PARAM_REGEX = "(\\?(\\w+(?:\\=[\\w\\-,]+|&)+)+)";
|
||||
|
||||
/**
|
||||
* Regex pattern for specifying any query param that has key = 'command' or not specific anything.
|
||||
@@ -202,6 +202,9 @@ public class CommandStrategyProvider {
|
||||
commandStrategies.put(CommandContext
|
||||
.resource("datatables\\/" + ALPHANUMBERIC_WITH_UNDERSCORE_REGEX + "\\/" + NUMBER_REGEX + OPTIONAL_QUERY_PARAM_REGEX)
|
||||
.method(GET).build(), "getDatatableEntryByAppTableIdCommandStrategy");
|
||||
commandStrategies.put(CommandContext.resource("datatables\\/" + ALPHANUMBERIC_WITH_UNDERSCORE_REGEX + "\\/" + NUMBER_REGEX + "\\/"
|
||||
+ NUMBER_REGEX + OPTIONAL_QUERY_PARAM_REGEX).method(GET).build(),
|
||||
"getDatatableEntryByAppTableIdAndDataTableIdCommandStrategy");
|
||||
commandStrategies.put(CommandContext.resource("loans\\/" + NUMBER_REGEX + OPTIONAL_COMMAND_PARAM_REGEX).method(PUT).build(),
|
||||
"modifyLoanApplicationCommandStrategy");
|
||||
commandStrategies.put(
|
||||
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* 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.command.internal;
|
||||
|
||||
import java.util.Map;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.batch.command.CommandStrategy;
|
||||
import org.apache.fineract.batch.command.CommandStrategyUtils;
|
||||
import org.apache.fineract.batch.domain.BatchRequest;
|
||||
import org.apache.fineract.batch.domain.BatchResponse;
|
||||
import org.apache.fineract.infrastructure.core.api.MutableUriInfo;
|
||||
import org.apache.fineract.infrastructure.dataqueries.api.DatatablesApiResource;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Implements {@link CommandStrategy} and get datatable by appTableId by data table id. It passes the contents of the
|
||||
* body from the BatchRequest to {@link DatatablesApiResource} and gets back the response. This class will also catch
|
||||
* any errors raised by {@link DatatablesApiResource} and map those errors to appropriate status codes in BatchResponse.
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class GetDatatableEntryByAppTableIdAndDataTableIdCommandStrategy implements CommandStrategy {
|
||||
|
||||
/**
|
||||
* Data table api resource {@link DatatablesApiResource}.
|
||||
*/
|
||||
private final DatatablesApiResource dataTablesApiResource;
|
||||
|
||||
@Override
|
||||
public BatchResponse execute(final BatchRequest request, @SuppressWarnings("unused") UriInfo uriInfo) {
|
||||
final MutableUriInfo parameterizedUriInfo = new MutableUriInfo(uriInfo);
|
||||
final BatchResponse response = new BatchResponse();
|
||||
final String responseBody;
|
||||
|
||||
response.setRequestId(request.getRequestId());
|
||||
response.setHeaders(request.getHeaders());
|
||||
|
||||
final String relativeUrl = request.getRelativeUrl();
|
||||
final String relativeUrlSubString = StringUtils.substringAfter(relativeUrl, "/");
|
||||
|
||||
// uriInfo will contain the query parameter value(s) that are sent in the actual batch uri.
|
||||
// for example: batches?enclosingTransaction=true
|
||||
// But the query parameters that are sent in the batch relative url has to be sent to
|
||||
// datatablesApiResource.getDatatable
|
||||
// To use the relative url query parameters
|
||||
// - Parse and fetch the query parameters sent in the relative url
|
||||
// (datatables/dt_123/1/2?genericResultSet=false)
|
||||
// - Add them to the MutableUriInfo query parameters list
|
||||
// - Call datatablesApiResource.getDatatableManyEntry(dataTable, appTableId, dataTableId, null, false, generic
|
||||
// resultSet, uriInfo)
|
||||
final String[] resources = StringUtils.split(relativeUrlSubString, "/");
|
||||
final String dataTableName = resources[0];
|
||||
final Long appTableId = Long.parseLong(resources[1]);
|
||||
final Long dataTableId = Long.parseLong(StringUtils.substringBefore(resources[2], "?"));
|
||||
boolean genericResultSet = false;
|
||||
if (relativeUrl.indexOf('?') > 0) {
|
||||
Map<String, String> queryParameters = CommandStrategyUtils.getQueryParameters(relativeUrl);
|
||||
// Add the query parameters sent in the relative URL to MutableUriInfo
|
||||
if (queryParameters.containsKey("genericResultSet")) {
|
||||
genericResultSet = Boolean.parseBoolean(queryParameters.get("genericResultSet"));
|
||||
}
|
||||
CommandStrategyUtils.addQueryParametersToUriInfo(parameterizedUriInfo, queryParameters);
|
||||
}
|
||||
// Calls 'getDatatableManyEntry' function from 'DatatablesApiResource' to
|
||||
// get the datatable details based on the appTableId
|
||||
responseBody = dataTablesApiResource.getDatatableManyEntry(dataTableName, appTableId, dataTableId, null, genericResultSet,
|
||||
parameterizedUriInfo);
|
||||
|
||||
response.setStatusCode(HttpStatus.SC_OK);
|
||||
|
||||
// Sets the response after retrieving the datatable
|
||||
response.setBody(responseBody);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
+7
-1
@@ -45,6 +45,7 @@ import org.apache.fineract.batch.command.internal.CreateTransactionLoanCommandSt
|
||||
import org.apache.fineract.batch.command.internal.DisburseLoanCommandStrategy;
|
||||
import org.apache.fineract.batch.command.internal.GetChargeByChargeExternalIdCommandStrategy;
|
||||
import org.apache.fineract.batch.command.internal.GetChargeByIdCommandStrategy;
|
||||
import org.apache.fineract.batch.command.internal.GetDatatableEntryByAppTableIdAndDataTableIdCommandStrategy;
|
||||
import org.apache.fineract.batch.command.internal.GetDatatableEntryByAppTableIdCommandStrategy;
|
||||
import org.apache.fineract.batch.command.internal.GetDatatableEntryByQueryCommandStrategy;
|
||||
import org.apache.fineract.batch.command.internal.GetLoanByExternalIdCommandStrategy;
|
||||
@@ -174,6 +175,9 @@ public class CommandStrategyProviderTest {
|
||||
mock(GetDatatableEntryByAppTableIdCommandStrategy.class)),
|
||||
Arguments.of("datatables/test_dt_table/123?genericResultSet=true", HttpMethod.GET,
|
||||
"getDatatableEntryByAppTableIdCommandStrategy", mock(GetDatatableEntryByAppTableIdCommandStrategy.class)),
|
||||
Arguments.of("datatables/test_dt_table/123/1?genericResultSet=true", HttpMethod.GET,
|
||||
"getDatatableEntryByAppTableIdAndDataTableIdCommandStrategy",
|
||||
mock(GetDatatableEntryByAppTableIdAndDataTableIdCommandStrategy.class)),
|
||||
Arguments.of("datatables/test_dt_table/123", HttpMethod.POST, "createDatatableEntryCommandStrategy",
|
||||
mock(CreateDatatableEntryCommandStrategy.class)),
|
||||
Arguments.of("datatables/test_dt_table/123/1", HttpMethod.PUT, "updateDatatableEntryOneToManyCommandStrategy",
|
||||
@@ -185,7 +189,9 @@ public class CommandStrategyProviderTest {
|
||||
Arguments.of("loans/123", HttpMethod.PUT, "modifyLoanApplicationCommandStrategy",
|
||||
mock(ModifyLoanApplicationCommandStrategy.class)),
|
||||
Arguments.of("datatables/test_dt_table/query?columnFilter=id&valueFilter=12&resultColumns=id", HttpMethod.GET,
|
||||
"getDatatableEntryByQueryCommandStrategy", mock(GetDatatableEntryByQueryCommandStrategy.class)));
|
||||
"getDatatableEntryByQueryCommandStrategy", mock(GetDatatableEntryByQueryCommandStrategy.class)),
|
||||
Arguments.of("datatables/test_dt_table/query?columnFilter=custom_id&valueFilter=10a62-d438-2319&resultColumns=id",
|
||||
HttpMethod.GET, "getDatatableEntryByQueryCommandStrategy", mock(GetDatatableEntryByQueryCommandStrategy.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
/**
|
||||
* 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.command.internal;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
import javax.ws.rs.HttpMethod;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import org.apache.commons.lang3.RandomUtils;
|
||||
import org.apache.fineract.batch.domain.BatchRequest;
|
||||
import org.apache.fineract.batch.domain.BatchResponse;
|
||||
import org.apache.fineract.infrastructure.core.api.MutableUriInfo;
|
||||
import org.apache.fineract.infrastructure.dataqueries.api.DatatablesApiResource;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
/**
|
||||
* Tests {GetDatatableEntryByAppTableIdAndDataTableIdCommandStrategy}.
|
||||
*/
|
||||
public class GetDatatableEntryByAppTableIdAndDataTableIdCommandStrategyTest {
|
||||
|
||||
/**
|
||||
* Query parameter provider.
|
||||
*
|
||||
* @return the test data stream
|
||||
*/
|
||||
private static Stream<Arguments> provideQueryParameters() {
|
||||
return Stream.of(Arguments.of(null, 0), Arguments.of("genericResultSet=true", 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test {@link GetDatatableEntryByAppTableIdAndDataTableIdCommandStrategy#execute} happy path scenario.
|
||||
*
|
||||
* @param queryParameter
|
||||
* the query parameter
|
||||
* @param numberOfQueryParams
|
||||
* number of query params are provided
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideQueryParameters")
|
||||
public void testExecuteSuccessScenario(final String queryParameter, final int numberOfQueryParams) {
|
||||
final TestContext testContext = new TestContext();
|
||||
|
||||
final Long loanId = RandomUtils.nextLong();
|
||||
final Long datatableId = RandomUtils.nextLong();
|
||||
final String datatableName = "dt_loan_xyz";
|
||||
final BatchRequest request = getBatchRequest(loanId, datatableId, queryParameter, datatableName);
|
||||
final String responseBody = "{\\\"columnHeaders\\\":[{}],\\\"data\\\":\\\"{}\\\"}";
|
||||
Boolean genericResultSet = false;
|
||||
if (queryParameter != null && queryParameter.contains("genericResultSet=true")) {
|
||||
genericResultSet = Boolean.TRUE;
|
||||
}
|
||||
given(testContext.dataTableApiResource.getDatatableManyEntry(eq(datatableName), eq(loanId), eq(datatableId), eq(null),
|
||||
eq(genericResultSet), any(UriInfo.class))).willReturn(responseBody);
|
||||
|
||||
final BatchResponse response = testContext.subjectToTest.execute(request, testContext.uriInfo);
|
||||
assertEquals(HttpStatus.SC_OK, response.getStatusCode());
|
||||
assertEquals(request.getRequestId(), response.getRequestId());
|
||||
assertEquals(request.getHeaders(), response.getHeaders());
|
||||
assertEquals(responseBody, response.getBody());
|
||||
|
||||
verify(testContext.dataTableApiResource).getDatatableManyEntry(eq(datatableName), eq(loanId), eq(datatableId), eq(null),
|
||||
eq(genericResultSet), testContext.uriInfoCaptor.capture());
|
||||
MutableUriInfo mutableUriInfo = testContext.uriInfoCaptor.getValue();
|
||||
assertThat(mutableUriInfo.getAdditionalQueryParameters()).hasSize(numberOfQueryParams);
|
||||
if (numberOfQueryParams > 0) {
|
||||
List<String> param = mutableUriInfo.getAdditionalQueryParameters().get("genericResultSet");
|
||||
assertEquals(param.get(0), "true");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a request with the given loan id.
|
||||
*
|
||||
* @param loanId
|
||||
* the loan id
|
||||
* @param queryParameter
|
||||
* the query parameter
|
||||
* @param datatableName
|
||||
* the datatable name
|
||||
* @return the {@link BatchRequest}
|
||||
*/
|
||||
private BatchRequest getBatchRequest(final Long loanId, final Long datatableId, final String queryParameter,
|
||||
final String datatableName) {
|
||||
final BatchRequest br = new BatchRequest();
|
||||
String relativeUrl = String.format("datatables/%s/%s/%s", datatableName, loanId, datatableId);
|
||||
if (queryParameter != null) {
|
||||
relativeUrl = relativeUrl + "?" + queryParameter;
|
||||
}
|
||||
|
||||
br.setRequestId(RandomUtils.nextLong());
|
||||
br.setRelativeUrl(relativeUrl);
|
||||
br.setMethod(HttpMethod.GET);
|
||||
br.setReference(RandomUtils.nextLong());
|
||||
br.setBody("{}");
|
||||
|
||||
return br;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private test context class used since testng runs in parallel to avoid state between tests
|
||||
*/
|
||||
private static final class TestContext {
|
||||
|
||||
/**
|
||||
* The subject under test.
|
||||
*/
|
||||
private final GetDatatableEntryByAppTableIdAndDataTableIdCommandStrategy subjectToTest;
|
||||
|
||||
/**
|
||||
* Mock of {@link UriInfo}
|
||||
*/
|
||||
@Mock
|
||||
private UriInfo uriInfo;
|
||||
|
||||
/**
|
||||
* Captor of {@link MutableUriInfo}.
|
||||
*/
|
||||
@Captor
|
||||
private ArgumentCaptor<MutableUriInfo> uriInfoCaptor;
|
||||
|
||||
/**
|
||||
* {@link DatatablesApiResource} mock.
|
||||
*/
|
||||
@Mock
|
||||
private DatatablesApiResource dataTableApiResource;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
private TestContext() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
subjectToTest = new GetDatatableEntryByAppTableIdAndDataTableIdCommandStrategy(dataTableApiResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-1
@@ -43,6 +43,7 @@ import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.apache.commons.lang3.RandomUtils;
|
||||
import org.apache.fineract.batch.command.internal.AdjustTransactionCommandStrategy;
|
||||
import org.apache.fineract.batch.command.internal.CreateTransactionLoanCommandStrategy;
|
||||
import org.apache.fineract.batch.command.internal.GetDatatableEntryByAppTableIdAndDataTableIdCommandStrategy;
|
||||
import org.apache.fineract.batch.domain.BatchRequest;
|
||||
import org.apache.fineract.batch.domain.BatchResponse;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
@@ -1326,6 +1327,7 @@ public class BatchApiTest {
|
||||
* @see org.apache.fineract.batch.command.internal.CreateDatatableEntryCommandStrategy
|
||||
* @see org.apache.fineract.batch.command.internal.UpdateDatatableEntryOneToManyCommandStrategy
|
||||
* @see org.apache.fineract.batch.command.internal.GetDatatableEntryByAppTableIdCommandStrategy
|
||||
* @see GetDatatableEntryByAppTableIdAndDataTableIdCommandStrategy
|
||||
*/
|
||||
@Test
|
||||
public void shouldReturnOkStatusOnSuccessfulCreateDataTableEntry() {
|
||||
@@ -1373,8 +1375,12 @@ public class BatchApiTest {
|
||||
final BatchRequest getDatatableEntriesRequest = BatchHelper.getDatatableByIdRequest(loanId, datatableName, null,
|
||||
updateDatatableEntryByEntryIdRequest.getReference());
|
||||
|
||||
// Get datatable entry by app table id batch request
|
||||
final BatchRequest getDatatableEntryByIdRequest = BatchHelper.getDatatableEntryByIdRequest(loanId, datatableName, "$.resourceId",
|
||||
null, updateDatatableEntryByEntryIdRequest.getReference());
|
||||
|
||||
final List<BatchRequest> batchRequestsDatatableEntries = Arrays.asList(createDatatableEntryRequest,
|
||||
updateDatatableEntryByEntryIdRequest, getDatatableEntriesRequest);
|
||||
updateDatatableEntryByEntryIdRequest, getDatatableEntriesRequest, getDatatableEntryByIdRequest);
|
||||
LOG.info("Batch Request : {}", BatchHelper.toJsonString(batchRequestsDatatableEntries));
|
||||
|
||||
final List<BatchResponse> responseDatatableBatch = BatchHelper.postBatchRequestsWithEnclosingTransaction(this.requestSpec,
|
||||
@@ -1385,9 +1391,12 @@ public class BatchApiTest {
|
||||
final BatchResponse batchResponse1 = responseDatatableBatch.get(0);
|
||||
final BatchResponse batchResponse2 = responseDatatableBatch.get(1);
|
||||
final BatchResponse batchResponse3 = responseDatatableBatch.get(2);
|
||||
final BatchResponse batchResponse4 = responseDatatableBatch.get(3);
|
||||
|
||||
Assertions.assertEquals(HttpStatus.SC_OK, batchResponse1.getStatusCode(), "Verify Status Code 200 for create datatable entry");
|
||||
Assertions.assertEquals(HttpStatus.SC_OK, batchResponse2.getStatusCode(), "Verify Status Code 200 for update datatable entry");
|
||||
Assertions.assertEquals(HttpStatus.SC_OK, batchResponse3.getStatusCode(), "Verify Status Code 200 for get datatable entries");
|
||||
Assertions.assertEquals(HttpStatus.SC_OK, batchResponse4.getStatusCode(), "Verify Status Code 200 for get datatable entry by id");
|
||||
|
||||
final String getDatatableEntriesResponse = batchResponse3.getBody();
|
||||
|
||||
|
||||
+32
@@ -1166,6 +1166,38 @@ public final class BatchHelper {
|
||||
return br;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a batch request to get datatable entry.
|
||||
*
|
||||
* @param loanId
|
||||
* the loan id
|
||||
* @param datatableName
|
||||
* the name of datatable
|
||||
* @param appTableId
|
||||
* the app table id
|
||||
* @param queryParameter
|
||||
* the query parameters
|
||||
* @param referenceId
|
||||
* the reference id
|
||||
* @return the {@link BatchRequest}
|
||||
*/
|
||||
public static BatchRequest getDatatableEntryByIdRequest(final Long loanId, final String datatableName, final String appTableId,
|
||||
final String queryParameter, final Long referenceId) {
|
||||
final BatchRequest br = new BatchRequest();
|
||||
String relativeUrl = String.format("datatables/%s/%s/%s", datatableName, loanId, appTableId);
|
||||
if (queryParameter != null) {
|
||||
relativeUrl = relativeUrl + "?" + queryParameter;
|
||||
}
|
||||
|
||||
br.setRequestId(4572L);
|
||||
br.setReference(referenceId);
|
||||
br.setRelativeUrl(relativeUrl);
|
||||
br.setMethod(HttpMethod.GET);
|
||||
br.setBody("{}");
|
||||
|
||||
return br;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a batch request to create datatable entry.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user