Compare commits

..

3 Commits

25 changed files with 201 additions and 278 deletions

View File

@ -102,14 +102,14 @@ jobs:
mvn_test:
executor: localstack/default
steps:
## - localstack/startup
- localstack/startup
- install_java17
- mvn_verify
mvn_deploy:
executor: localstack/default
steps:
## - localstack/startup
- localstack/startup
- install_java17
- mvn_verify
- mvn_jar_deploy

View File

@ -319,10 +319,8 @@ public class DMLAuditAction extends AbstractQActionFunction<DMLAuditInput, DMLAu
if(detailRecord != null)
{
////////////////////////////////////////////////////////////////////
// useful if doing dev in here - but overkill for any other time. //
////////////////////////////////////////////////////////////////////
// LOG.debug("Returning with message: " + detailRecord.getValueString("message"));
LOG.debug("Returning with message: " + detailRecord.getValueString("message"));
detailRecord.withValue("fieldName", fieldName);
return (Optional.of(detailRecord));
}

View File

@ -28,7 +28,6 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.tables.UniqueKey;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
/*******************************************************************************
@ -56,7 +55,7 @@ public interface GetInterface
{
QTableMetaData table = getInput.getTable();
boolean foundMatch = false;
for(UniqueKey uniqueKey : CollectionUtils.nonNullList(table.getUniqueKeys()))
for(UniqueKey uniqueKey : table.getUniqueKeys())
{
if(new HashSet<>(uniqueKey.getFieldNames()).equals(getInput.getUniqueKey().keySet()))
{

View File

@ -28,9 +28,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import com.kingsrook.qqq.backend.core.actions.audits.AuditAction;
import com.kingsrook.qqq.backend.core.context.QContext;
import com.kingsrook.qqq.backend.core.model.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.security.RecordSecurityLock;
import com.kingsrook.qqq.backend.core.model.metadata.security.RecordSecurityLockFilters;
@ -55,41 +52,6 @@ public class AuditSingleInput
/*******************************************************************************
** Constructor
**
*******************************************************************************/
public AuditSingleInput()
{
}
/*******************************************************************************
** Constructor
**
*******************************************************************************/
public AuditSingleInput(QTableMetaData table, QRecord record, String auditMessage)
{
setAuditTableName(table.getName());
setRecordId(record.getValueInteger(table.getPrimaryKeyField()));
setSecurityKeyValues(AuditAction.getRecordSecurityKeyValues(table, record, Optional.empty()));
setMessage(auditMessage);
}
/*******************************************************************************
** Constructor
**
*******************************************************************************/
public AuditSingleInput(String tableName, QRecord record, String auditMessage)
{
this(QContext.getQInstance().getTable(tableName), record, auditMessage);
}
/*******************************************************************************
** Getter for auditTableName
*******************************************************************************/

View File

@ -131,17 +131,6 @@ public class ProcessSummaryFilterLink implements ProcessSummaryLineInterface
/*******************************************************************************
**
*******************************************************************************/
@Override
public String getMessage()
{
return getFullText();
}
/*******************************************************************************
** Setter for status
**

View File

@ -182,7 +182,6 @@ public class ProcessSummaryLine implements ProcessSummaryLineInterface
** Getter for message
**
*******************************************************************************/
@Override
public String getMessage()
{
return message;

View File

@ -38,10 +38,6 @@ public interface ProcessSummaryLineInterface extends Serializable
*******************************************************************************/
Status getStatus();
/*******************************************************************************
**
*******************************************************************************/
String getMessage();
/*******************************************************************************
** meant to be called by framework, after process is complete, give the

View File

@ -95,17 +95,6 @@ public class ProcessSummaryRecordLink implements ProcessSummaryLineInterface
/*******************************************************************************
**
*******************************************************************************/
@Override
public String getMessage()
{
return getFullText();
}
/*******************************************************************************
**
*******************************************************************************/

View File

@ -89,34 +89,6 @@ public class ExtractViaBasepullQueryStep extends ExtractViaQueryStep
/*******************************************************************************
** Let a subclass know if getQueryFilter will use the "default filter" (e.g., from
** our base class, which would come from values passed in to the process), or if
** the BasePull Query would be used (e.g., for a scheduled job).
*******************************************************************************/
protected boolean willTheBasePullQueryBeUsed(RunBackendStepInput runBackendStepInput)
{
try
{
super.getQueryFilter(runBackendStepInput);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// if super.getQueryFilter returned - then - there's a default query to use (e.g., a user selecting rows on a screen). //
// this means we won't use the BasePull query, so return a false here. //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
return (false);
}
catch(QException qe)
{
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// if we catch here, assume that is because there was no default filter - in which case - we'll use the BasePull Query //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
return (true);
}
}
/*******************************************************************************
**
*******************************************************************************/

View File

@ -35,10 +35,8 @@ import java.util.Set;
import java.util.stream.Collectors;
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
import com.kingsrook.qqq.backend.core.actions.values.QPossibleValueTranslator;
import com.kingsrook.qqq.backend.core.context.QContext;
import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.logging.QLogger;
import com.kingsrook.qqq.backend.core.model.actions.audits.AuditSingleInput;
import com.kingsrook.qqq.backend.core.model.actions.processes.ProcessSummaryLine;
import com.kingsrook.qqq.backend.core.model.actions.processes.ProcessSummaryLineInterface;
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
@ -75,21 +73,18 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
private ProcessSummaryLine okToInsert = StandardProcessSummaryLineProducer.getOkToInsertLine();
private ProcessSummaryLine okToUpdate = StandardProcessSummaryLineProducer.getOkToUpdateLine();
private ProcessSummaryLine willNotInsert = new ProcessSummaryLine(Status.INFO)
.withMessageSuffix("because of this process' configuration.")
.withSingularFutureMessage("will not be inserted ")
.withPluralFutureMessage("will not be inserted ")
.withSingularPastMessage("was not inserted ")
.withPluralPastMessage("were not inserted ");
private ProcessSummaryLine willNotUpdate = new ProcessSummaryLine(Status.INFO)
.withMessageSuffix("because of this process' configuration.")
.withSingularFutureMessage("will not be updated ")
.withPluralFutureMessage("will not be updated ")
.withSingularPastMessage("was not updated ")
.withPluralPastMessage("were not updated ");
private ProcessSummaryLine errorMissingKeyField = new ProcessSummaryLine(Status.ERROR)
.withMessageSuffix("missing a value for the key field.")
.withSingularFutureMessage("will not be synced, because it is ")
@ -97,15 +92,7 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
.withSingularPastMessage("was not synced, because it is ")
.withPluralPastMessage("were not synced, because they are ");
private ProcessSummaryLine unspecifiedError = new ProcessSummaryLine(Status.ERROR)
.withMessageSuffix("of an unexpected error: ")
.withSingularFutureMessage("will not be synced, ")
.withPluralFutureMessage("will not be synced, ")
.withSingularPastMessage("was not synced, ")
.withPluralPastMessage("were not synced, ");
protected RunBackendStepInput runBackendStepInput = null;
protected RunBackendStepOutput runBackendStepOutput = null;
protected RecordLookupHelper recordLookupHelper = null;
private QPossibleValueTranslator possibleValueTranslator;
@ -118,17 +105,16 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
@Override
public ArrayList<ProcessSummaryLineInterface> getProcessSummary(RunBackendStepOutput runBackendStepOutput, boolean isForResultScreen)
{
return StandardProcessSummaryLineProducer.toArrayList(okToInsert, okToUpdate, errorMissingKeyField, unspecifiedError, willNotInsert, willNotUpdate);
}
/*******************************************************************************
**
*******************************************************************************/
protected ArrayList<ProcessSummaryLineInterface> getErrorProcessSummaryLines(RunBackendStepOutput runBackendStepOutput, boolean isForResultScreen)
ArrayList<ProcessSummaryLineInterface> processSummaryLineList = StandardProcessSummaryLineProducer.toArrayList(okToInsert, okToUpdate, errorMissingKeyField);
if(willNotInsert.getCount() > 0)
{
return StandardProcessSummaryLineProducer.toArrayList(errorMissingKeyField, unspecifiedError);
processSummaryLineList.add(willNotInsert);
}
if(willNotUpdate.getCount() > 0)
{
processSummaryLineList.add(willNotUpdate);
}
return (processSummaryLineList);
}
@ -207,7 +193,6 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
}
this.runBackendStepInput = runBackendStepInput;
this.runBackendStepOutput = runBackendStepOutput;
SyncProcessConfig config = getSyncProcessConfig();
@ -257,7 +242,6 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
Set<Serializable> processedSourceKeys = new HashSet<>();
for(QRecord sourceRecord : runBackendStepInput.getRecords())
{
Serializable sourcePrimaryKey = sourceRecord.getValue(QContext.getQInstance().getTable(config.sourceTable).getPrimaryKeyField());
Serializable sourceKeyValue = sourceRecord.getValue(sourceTableKeyField);
if(processedSourceKeys.contains(sourceKeyValue))
{
@ -268,7 +252,7 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
if(sourceKeyValue == null || "".equals(sourceKeyValue))
{
errorMissingKeyField.incrementCountAndAddPrimaryKey(sourcePrimaryKey);
errorMissingKeyField.incrementCount();
try
{
@ -287,58 +271,43 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
//////////////////////////////////////////////////////////////
// look for the existing record, to determine insert/update //
//////////////////////////////////////////////////////////////
try
{
QRecord existingRecord = getExistingRecord(existingRecordsByForeignKey, destinationForeignKeyField, sourceKeyValue);
QRecord recordToStore;
if(existingRecord != null && config.performUpdates)
{
recordToStore = existingRecord;
okToUpdate.incrementCount();
}
else if(existingRecord == null && config.performInserts)
{
recordToStore = new QRecord();
okToInsert.incrementCount();
}
else
{
if(existingRecord != null)
{
LOG.info("Skipping storing existing record because this sync process is set to not perform updates");
willNotInsert.incrementCountAndAddPrimaryKey(sourcePrimaryKey);
willNotInsert.incrementCount();
}
else
{
LOG.info("Skipping storing new record because this sync process is set to not perform inserts");
willNotUpdate.incrementCountAndAddPrimaryKey(sourcePrimaryKey);
willNotUpdate.incrementCount();
}
continue;
}
//////////////////////////////////////////////////////////////////////////////////
// if we received a record to store add to the output records and summary lines //
//////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
// if we received a record to store add to the output records //
////////////////////////////////////////////////////////////////
recordToStore = populateRecordToStore(runBackendStepInput, recordToStore, sourceRecord);
if(recordToStore != null)
{
if(existingRecord != null)
{
okToUpdate.incrementCountAndAddPrimaryKey(sourcePrimaryKey);
}
else
{
okToInsert.incrementCountAndAddPrimaryKey(sourcePrimaryKey);
}
runBackendStepOutput.addRecord(recordToStore);
}
}
catch(Exception e)
{
unspecifiedError.incrementCountAndAddPrimaryKey(sourcePrimaryKey);
unspecifiedError.setMessageSuffix(unspecifiedError.getMessageSuffix() + e.getMessage());
}
}
////////////////////////////////////////////////
// populate possible-values for review screen //
@ -457,17 +426,4 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
}
}
/*******************************************************************************
** Let the subclass "easily" add an audit to be inserted on the Execute step.
*******************************************************************************/
protected void addAuditForExecuteStep(AuditSingleInput auditSingleInput)
{
if(StreamedETLWithFrontendProcess.STEP_NAME_EXECUTE.equals(this.runBackendStepInput.getStepName()))
{
this.runBackendStepOutput.addAuditSingleInput(auditSingleInput);
}
}
}

View File

@ -26,6 +26,7 @@ import java.io.IOException;
import java.time.Instant;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
@ -222,6 +223,67 @@ public class JsonUtils
/*******************************************************************************
** Sorts all fields recursively in all objects in a json object
**
*******************************************************************************/
private static Object sortJSON(Object o, int depth) throws Exception
{
///////////////////////////////////////////////////////
// this should only be done on json objects or array //
///////////////////////////////////////////////////////
if(depth == 0 && !(o instanceof JSONObject) && !(o instanceof JSONArray))
{
throw (new Exception("Object must be of type JSONObject or JSONArray in order to sort"));
}
if(o instanceof JSONObject jsonObject)
{
////////////////////////////////////////////////////////////////////
// if json object, create a new object, sort keys, and add to the //
// new object passing values to this sort method recursively //
////////////////////////////////////////////////////////////////////
JSONObject returnObject = new JSONObject();
List<String> keys = new ArrayList<>(jsonObject.keySet());
Collections.sort(keys);
for(String key : keys)
{
returnObject.put(key, sortJSON(jsonObject.get(key), ++depth));
}
return (returnObject);
}
else if(o instanceof JSONArray jsonArray)
{
/////////////////////////////////////////////////////////////////////////
// if this is an array, same as above, but no sorting needed (i think) //
/////////////////////////////////////////////////////////////////////////
JSONArray returnObject = new JSONArray();
for(int i = 0; i < jsonArray.length(); i++)
{
returnObject.put(i, sortJSON(jsonArray.get(i), ++depth));
}
return (returnObject);
}
return (o);
}
/*******************************************************************************
** Sorts all fields recursively in all objects in a json object
**
*******************************************************************************/
public static Object sortJSON(Object o) throws Exception
{
return (sortJSON(o, 0));
}
/*******************************************************************************
** De-serialize a json string into a JSONArray (string must start with "[")
**

View File

@ -23,17 +23,14 @@ package com.kingsrook.qqq.backend.core.processes.implementations.basepull;
import java.time.Instant;
import java.util.Map;
import com.kingsrook.qqq.backend.core.BaseTest;
import com.kingsrook.qqq.backend.core.actions.processes.RunProcessAction;
import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
import com.kingsrook.qqq.backend.core.processes.implementations.etl.streamedwithfrontend.StreamedETLWithFrontendProcess;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -74,27 +71,4 @@ class ExtractViaBasepullQueryStepTest extends BaseTest
assertTrue(queryFilter.getOrderBys().get(0).getIsAscending());
}
/*******************************************************************************
**
*******************************************************************************/
@Test
void testWillTheBasePullQueryBeUsed()
{
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// only time the base-pull query will be used is if there isn't a filter or records in the process input. //
////////////////////////////////////////////////////////////////////////////////////////////////////////////
assertTrue(new ExtractViaBasepullQueryStep().willTheBasePullQueryBeUsed(new RunBackendStepInput()));
assertFalse(new ExtractViaBasepullQueryStep().willTheBasePullQueryBeUsed(new RunBackendStepInput()
.withValues(Map.of("recordIds", "1,2,3", StreamedETLWithFrontendProcess.FIELD_SOURCE_TABLE, "person"))));
assertFalse(new ExtractViaBasepullQueryStep().willTheBasePullQueryBeUsed(new RunBackendStepInput()
.withValues(Map.of(StreamedETLWithFrontendProcess.FIELD_DEFAULT_QUERY_FILTER, new QQueryFilter()))));
assertFalse(new ExtractViaBasepullQueryStep().willTheBasePullQueryBeUsed(new RunBackendStepInput()
.withValues(Map.of("queryFilterJson", "{}"))));
}
}

View File

@ -40,6 +40,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@ -138,6 +139,86 @@ class JsonUtilsTest extends BaseTest
/*******************************************************************************
**
*******************************************************************************/
@Test
public void test_sortJSONArray() throws Exception
{
JSONArray jsonArray1 = new JSONArray("""
[
{
"Foo": "Bar",
"Baz": [1, 2, 3]
}
]
""");
JSONArray jsonArray2 = new JSONArray("""
[
{
"Baz": [1, 2, 3],
"Foo": "Bar"
}
]
""");
JSONArray sortedJSONArray1 = (JSONArray) JsonUtils.sortJSON(jsonArray1);
JSONArray sortedJSONArray2 = (JSONArray) JsonUtils.sortJSON(jsonArray2);
assertEquals(sortedJSONArray1.toString(), sortedJSONArray2.toString());
}
/*******************************************************************************
**
*******************************************************************************/
@Test
public void test_sortJSONObject() throws Exception
{
JSONObject jsonObject1 = new JSONObject("""
{
"Foo": "Bar",
"Baz": [1, 2, 3]
}
""");
JSONObject jsonObject2 = new JSONObject("""
{
"Baz": [1, 2, 3],
"Foo": "Bar"
}
""");
JSONObject sortedJSONObject1 = (JSONObject) JsonUtils.sortJSON(jsonObject1);
JSONObject sortedJSONObject2 = (JSONObject) JsonUtils.sortJSON(jsonObject2);
assertEquals(sortedJSONObject1.toString(), sortedJSONObject2.toString());
JSONObject bigObject1 = new JSONObject("""
{ "cubeiq": { "settings": { "setting": [ { "maxruntime": 60, "maxnonimproveiters": 750, "settingsid": "Box Default", "sequencemixok": true } ] }, "containerstoload": { "containertoload": [ { "containernum": 99, "loadid": "4814b7a4-dc8a-43b8-8772-af86cb11d9a0", "containerid": "25_4976f3f8-1208-430f-aee4-59fc1d1f4b3f" } ] }, "loads": { "load": [ { "date": "1-1-2015", "notes": "", "loadid": "4814b7a4-dc8a-43b8-8772-af86cb11d9a0" } ] }, "stages": { "stage": [ { "loadid": "4814b7a4-dc8a-43b8-8772-af86cb11d9a0", "stage": 1 } ] }, "containers": { "container": [ { "depth": 5, "bottomtotoploading": false, "width": 5, "action": "overwrite", "partialloadonfloor": true, "settingsid": "Box Default", "containerid": "25_4976f3f8-1208-430f-aee4-59fc1d1f4b3f", "type": "Rectangular", "height": 10 } ] }, "productstoload": { "producttoload": [ { "quantity": 1, "loadid": "4814b7a4-dc8a-43b8-8772-af86cb11d9a0", "productid": "DRY-ICE", "batch": 1 } ] }, "products": { "product": [ { "productid": "DRY-ICE", "color": 16760576, "length": 3, "weight": 1, "maxinlayer": 999999, "type": "Box", "sideupok": true, "endupok": true, "turnable": true, "bottomonly": false, "width": 3, "toponly": false, "flatok": true, "height": 1 } ] } } }
""");
JSONObject bigObject2 = new JSONObject("""
{ "cubeiq": { "containerstoload": { "containertoload": [ { "containernum": 99, "loadid": "4814b7a4-dc8a-43b8-8772-af86cb11d9a0", "containerid": "25_4976f3f8-1208-430f-aee4-59fc1d1f4b3f" } ] }, "settings": { "setting": [ { "maxruntime": 60, "maxnonimproveiters": 750, "settingsid": "Box Default", "sequencemixok": true } ] }, "loads": { "load": [ { "date": "1-1-2015", "notes": "", "loadid": "4814b7a4-dc8a-43b8-8772-af86cb11d9a0" } ] }, "stages": { "stage": [ { "loadid": "4814b7a4-dc8a-43b8-8772-af86cb11d9a0", "stage": 1 } ] }, "containers": { "container": [ { "depth": 5, "bottomtotoploading": false, "action": "overwrite", "width": 5, "partialloadonfloor": true, "settingsid": "Box Default", "containerid": "25_4976f3f8-1208-430f-aee4-59fc1d1f4b3f", "type": "Rectangular", "height": 10 } ] }, "products": { "product": [ { "productid": "DRY-ICE", "color": 16760576, "weight": 1, "length": 3, "sideupok": true, "maxinlayer": 999999, "type": "Box", "endupok": true, "toponly": false, "turnable": true, "bottomonly": false, "width": 3, "flatok": true, "height": 1 } ] }, "productstoload": { "producttoload": [ { "quantity": 1, "loadid": "4814b7a4-dc8a-43b8-8772-af86cb11d9a0", "productid": "DRY-ICE", "batch": 1 } ] } } }
""");
sortedJSONObject1 = (JSONObject) JsonUtils.sortJSON(bigObject1);
sortedJSONObject2 = (JSONObject) JsonUtils.sortJSON(bigObject2);
assertEquals(sortedJSONObject1.toString(), sortedJSONObject2.toString());
}
/*******************************************************************************
**
*******************************************************************************/
@Test
public void test_sortNonJSONThrows() throws Exception
{
assertThatThrownBy(() -> JsonUtils.sortJSON("derp"))
.hasMessageContaining("must be of type");
}
/*******************************************************************************
**
*******************************************************************************/

View File

@ -27,7 +27,6 @@ import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.ArrayList;
@ -787,7 +786,7 @@ public class BaseAPIActionUtil
try(CloseableHttpClient client = HttpClients.custom().setConnectionManager(new PoolingHttpClientConnectionManager()).build())
{
HttpPost request = new HttpPost(fullURL);
request.setEntity(new StringEntity(postBody, getCharsetForEntity()));
request.setEntity(new StringEntity(postBody));
if(setCredentialsInHeader)
{
@ -830,16 +829,6 @@ public class BaseAPIActionUtil
/*******************************************************************************
** Let a subclass change what charset to use for entities (bodies) being posted/put/etc.
*******************************************************************************/
protected static Charset getCharsetForEntity()
{
return StandardCharsets.UTF_8;
}
/*******************************************************************************
** one-line method, factored out so mock/tests can override
*******************************************************************************/
@ -925,7 +914,7 @@ public class BaseAPIActionUtil
body.put(wrapperObjectName, new JSONObject(json));
json = body.toString();
}
return (new StringEntity(json, getCharsetForEntity()));
return (new StringEntity(json));
}
@ -954,7 +943,7 @@ public class BaseAPIActionUtil
body.put(wrapperObjectName, new JSONArray(json));
json = body.toString();
}
return (new StringEntity(json, getCharsetForEntity()));
return (new StringEntity(json));
}
catch(Exception e)
{

View File

@ -63,18 +63,14 @@ import com.kingsrook.qqq.backend.module.api.model.OutboundAPILog;
import com.kingsrook.qqq.backend.module.api.model.OutboundAPILogMetaDataProvider;
import com.kingsrook.qqq.backend.module.api.model.metadata.APIBackendMetaData;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.json.JSONArray;
import org.json.JSONObject;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
/*******************************************************************************
@ -343,32 +339,10 @@ class BaseAPIActionUtilTest extends BaseTest
mockApiUtilsHelper.enqueueMockResponse("""
{"id": 6}
""");
mockApiUtilsHelper.withMockRequestAsserter(httpRequestBase ->
{
HttpEntity entity = ((HttpEntityEnclosingRequestBase) httpRequestBase).getEntity();
byte[] bytes = entity.getContent().readAllBytes();
String requestBody = new String(bytes, StandardCharsets.UTF_8);
///////////////////////////////////////
// default ISO-8559-1: ... a0 ... //
// updated UTF-8: ... c2 a0 ... //
///////////////////////////////////////
byte previousByte = 0;
for(byte b : bytes)
{
if(b == (byte) 0xa0 && previousByte != (byte) 0xc2)
{
fail("Found byte 0xa0 (without being prefixed by 0xc2) - so this is invalid UTF-8!");
}
previousByte = b;
}
assertThat(requestBody).contains("van Houten");
});
InsertInput insertInput = new InsertInput();
insertInput.setTableName(TestUtils.MOCK_TABLE_NAME);
insertInput.setRecords(List.of(new QRecord().withValue("name", "Milhouse van Houten")));
insertInput.setRecords(List.of(new QRecord().withValue("name", "Milhouse")));
InsertOutput insertOutput = new InsertAction().execute(insertInput);
assertEquals(6, insertOutput.getRecords().get(0).getValueInteger("id"));
}

View File

@ -33,9 +33,7 @@
<properties>
<!-- props specifically to this module -->
<!-- temp - disable this when localstack is fixed -->
<coverage.haltOnFailure>false</coverage.haltOnFailure>
<!-- none at this time -->
</properties>
<dependencies>

View File

@ -44,7 +44,6 @@ import com.kingsrook.qqq.backend.module.filesystem.s3.S3BackendModuleSubclassFor
import com.kingsrook.qqq.backend.module.filesystem.s3.actions.AbstractS3Action;
import com.kingsrook.qqq.backend.module.filesystem.s3.model.metadata.S3BackendMetaData;
import com.kingsrook.qqq.backend.module.filesystem.s3.model.metadata.S3TableBackendDetails;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -53,7 +52,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
/*******************************************************************************
** Unit test for FilesystemSyncProcess using S3 backend
*******************************************************************************/
@Disabled("Because localstack won't start")
class FilesystemSyncProcessS3Test extends BaseS3Test
{

View File

@ -31,14 +31,12 @@ import com.kingsrook.qqq.backend.module.filesystem.TestUtils;
import com.kingsrook.qqq.backend.module.filesystem.exceptions.FilesystemException;
import com.kingsrook.qqq.backend.module.filesystem.s3.actions.AbstractS3Action;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
/*******************************************************************************
** Unit test for S3BackendModule
*******************************************************************************/
@Disabled("Because localstack won't start")
public class S3BackendModuleTest extends BaseS3Test
{
private final String PATH_THAT_WONT_EXIST = "some/path/that/wont/exist";

View File

@ -28,14 +28,12 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountOutput;
import com.kingsrook.qqq.backend.module.filesystem.TestUtils;
import com.kingsrook.qqq.backend.module.filesystem.s3.BaseS3Test;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
/*******************************************************************************
**
*******************************************************************************/
@Disabled("Because localstack won't start")
public class S3CountActionTest extends BaseS3Test
{

View File

@ -26,7 +26,6 @@ import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteInput;
import com.kingsrook.qqq.backend.module.filesystem.s3.BaseS3Test;
import org.apache.commons.lang.NotImplementedException;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertThrows;
@ -34,7 +33,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
/*******************************************************************************
**
*******************************************************************************/
@Disabled("Because localstack won't start")
public class S3DeleteActionTest extends BaseS3Test
{

View File

@ -35,7 +35,6 @@ import com.kingsrook.qqq.backend.module.filesystem.base.FilesystemRecordBackendD
import com.kingsrook.qqq.backend.module.filesystem.s3.BaseS3Test;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.NotImplementedException;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@ -45,7 +44,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
/*******************************************************************************
**
*******************************************************************************/
@Disabled("Because localstack won't start")
public class S3InsertActionTest extends BaseS3Test
{

View File

@ -29,14 +29,12 @@ import com.kingsrook.qqq.backend.module.filesystem.TestUtils;
import com.kingsrook.qqq.backend.module.filesystem.base.FilesystemRecordBackendDetailFields;
import com.kingsrook.qqq.backend.module.filesystem.s3.BaseS3Test;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
/*******************************************************************************
**
*******************************************************************************/
@Disabled("Because localstack won't start")
public class S3QueryActionTest extends BaseS3Test
{

View File

@ -26,7 +26,6 @@ import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
import com.kingsrook.qqq.backend.module.filesystem.s3.BaseS3Test;
import org.apache.commons.lang.NotImplementedException;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertThrows;
@ -34,7 +33,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
/*******************************************************************************
**
*******************************************************************************/
@Disabled("Because localstack won't start")
public class S3UpdateActionTest extends BaseS3Test
{

View File

@ -28,7 +28,6 @@ import java.util.List;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.kingsrook.qqq.backend.module.filesystem.s3.BaseS3Test;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -36,7 +35,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
/*******************************************************************************
**
*******************************************************************************/
@Disabled("Because localstack won't start")
public class S3UtilsTest extends BaseS3Test
{

View File

@ -193,7 +193,8 @@ public abstract class AbstractRDBMSAction implements QActionInterface
{
try
{
if(table.getFields().containsKey(fieldName))
QFieldMetaData field = table.getField(fieldName);
if(field != null)
{
record.setValue(fieldName, value);
}