diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/ExecuteCodeAction.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/ExecuteCodeAction.java index 024305ec..51b7b6cb 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/ExecuteCodeAction.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/ExecuteCodeAction.java @@ -231,7 +231,19 @@ public class ExecuteCodeAction *******************************************************************************/ public static void addApiUtilityToContext(Map context, ScriptRevision scriptRevision) { - if(!StringUtils.hasContent(scriptRevision.getApiName()) || !StringUtils.hasContent(scriptRevision.getApiVersion())) + addApiUtilityToContext(context, scriptRevision.getApiName(), scriptRevision.getApiVersion()); + } + + + + /******************************************************************************* + ** Try to (dynamically) load the ApiScriptUtils object from the api middleware + ** module -- in case the runtime doesn't have that module deployed (e.g, not in + ** the project pom). + *******************************************************************************/ + public static void addApiUtilityToContext(Map context, String apiName, String apiVersion) + { + if(!StringUtils.hasContent(apiName) || !StringUtils.hasContent(apiVersion)) { return; } @@ -239,7 +251,7 @@ public class ExecuteCodeAction try { Class apiScriptUtilsClass = Class.forName("com.kingsrook.qqq.api.utils.ApiScriptUtils"); - Object apiScriptUtilsObject = apiScriptUtilsClass.getConstructor(String.class, String.class).newInstance(scriptRevision.getApiName(), scriptRevision.getApiVersion()); + Object apiScriptUtilsObject = apiScriptUtilsClass.getConstructor(String.class, String.class).newInstance(apiName, apiVersion); context.put("api", (Serializable) apiScriptUtilsObject); } catch(ClassNotFoundException e) diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/logging/Log4jCodeExecutionLogger.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/logging/Log4jCodeExecutionLogger.java index 8b55e6f5..2fe84d4a 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/logging/Log4jCodeExecutionLogger.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/logging/Log4jCodeExecutionLogger.java @@ -41,6 +41,7 @@ public class Log4jCodeExecutionLogger implements QCodeExecutionLoggerInterface private QCodeReference qCodeReference; private String uuid = UUID.randomUUID().toString(); + private boolean includeUUID = true; /******************************************************************************* @@ -52,7 +53,7 @@ public class Log4jCodeExecutionLogger implements QCodeExecutionLoggerInterface this.qCodeReference = executeCodeInput.getCodeReference(); String inputString = StringUtils.safeTruncate(ValueUtils.getValueAsString(executeCodeInput.getInput()), 250, "..."); - LOG.info("Starting script execution: " + qCodeReference.getName() + ", uuid: " + uuid + ", with input: " + inputString); + LOG.info("Starting script execution: " + qCodeReference.getName() + (includeUUID ? ", uuid: " + uuid : "") + ", with input: " + inputString); } @@ -63,7 +64,7 @@ public class Log4jCodeExecutionLogger implements QCodeExecutionLoggerInterface @Override public void acceptLogLine(String logLine) { - LOG.info("Script log: " + uuid + ": " + logLine); + LOG.info("Script log: " + (includeUUID ? uuid + ": " : "") + logLine); } @@ -74,7 +75,7 @@ public class Log4jCodeExecutionLogger implements QCodeExecutionLoggerInterface @Override public void acceptException(Exception exception) { - LOG.info("Script Exception: " + uuid, exception); + LOG.info("Script Exception: " + (includeUUID ? uuid : ""), exception); } @@ -86,7 +87,38 @@ public class Log4jCodeExecutionLogger implements QCodeExecutionLoggerInterface public void acceptExecutionEnd(Serializable output) { String outputString = StringUtils.safeTruncate(ValueUtils.getValueAsString(output), 250, "..."); - LOG.info("Finished script execution: " + qCodeReference.getName() + ", uuid: " + uuid + ", with output: " + outputString); + LOG.info("Finished script execution: " + qCodeReference.getName() + (includeUUID ? ", uuid: " + uuid : "") + ", with output: " + outputString); + } + + + + /******************************************************************************* + ** Getter for includeUUID + *******************************************************************************/ + public boolean getIncludeUUID() + { + return (this.includeUUID); + } + + + + /******************************************************************************* + ** Setter for includeUUID + *******************************************************************************/ + public void setIncludeUUID(boolean includeUUID) + { + this.includeUUID = includeUUID; + } + + + + /******************************************************************************* + ** Fluent setter for includeUUID + *******************************************************************************/ + public Log4jCodeExecutionLogger withIncludeUUID(boolean includeUUID) + { + this.includeUUID = includeUUID; + return (this); } } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/logging/SystemOutExecutionLogger.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/logging/SystemOutExecutionLogger.java new file mode 100644 index 00000000..d0911628 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/scripts/logging/SystemOutExecutionLogger.java @@ -0,0 +1,88 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2022. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.kingsrook.qqq.backend.core.actions.scripts.logging; + + +import java.io.Serializable; +import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput; +import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; +import com.kingsrook.qqq.backend.core.utils.ValueUtils; + + +/******************************************************************************* + ** Implementation of a code execution logger that logs to System.out and + ** System.err (for exceptions) + *******************************************************************************/ +public class SystemOutExecutionLogger implements QCodeExecutionLoggerInterface +{ + private QCodeReference qCodeReference; + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Override + public void acceptExecutionStart(ExecuteCodeInput executeCodeInput) + { + this.qCodeReference = executeCodeInput.getCodeReference(); + + String inputString = ValueUtils.getValueAsString(executeCodeInput.getInput()); + System.out.println("Starting script execution: " + qCodeReference.getName() + ", with input: " + inputString); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Override + public void acceptLogLine(String logLine) + { + System.out.println("Script log: " + logLine); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Override + public void acceptException(Exception exception) + { + System.out.println("Script Exception: " + exception.getMessage()); + exception.printStackTrace(); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Override + public void acceptExecutionEnd(Serializable output) + { + String outputString = ValueUtils.getValueAsString(output); + System.out.println("Finished script execution: " + qCodeReference.getName() + ", with output: " + outputString); + } + +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/scripts/StoreScriptRevisionProcessStep.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/scripts/StoreScriptRevisionProcessStep.java index 73bc4e13..f7b94ab9 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/scripts/StoreScriptRevisionProcessStep.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/scripts/StoreScriptRevisionProcessStep.java @@ -159,6 +159,15 @@ public class StoreScriptRevisionProcessStep implements BackendStep .toQRecord()); } } + else if(StringUtils.hasContent(input.getValueString("contents"))) + { + scriptRevisionFileRecords = new ArrayList<>(); + scriptRevisionFileRecords.add(new ScriptRevisionFile() + .withScriptRevisionId(scriptRevisionId) + .withFileName("Script.js") + .withContents(input.getValueString("contents")) + .toQRecord()); + } if(CollectionUtils.nullSafeHasContents(scriptRevisionFileRecords)) { diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/scripts/ExecuteCodeActionTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/scripts/ExecuteCodeActionTest.java index 219b2222..4f661a3e 100644 --- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/scripts/ExecuteCodeActionTest.java +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/scripts/ExecuteCodeActionTest.java @@ -31,6 +31,7 @@ import com.kingsrook.qqq.backend.core.actions.scripts.logging.Log4jCodeExecution import com.kingsrook.qqq.backend.core.actions.scripts.logging.NoopCodeExecutionLogger; import com.kingsrook.qqq.backend.core.actions.scripts.logging.QCodeExecutionLoggerInterface; import com.kingsrook.qqq.backend.core.actions.scripts.logging.StoreScriptLogAndScriptLogLineExecutionLogger; +import com.kingsrook.qqq.backend.core.actions.scripts.logging.SystemOutExecutionLogger; import com.kingsrook.qqq.backend.core.context.QContext; import com.kingsrook.qqq.backend.core.exceptions.QCodeException; import com.kingsrook.qqq.backend.core.exceptions.QException; @@ -112,6 +113,21 @@ class ExecuteCodeActionTest extends BaseTest + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testSystemOutLogger() throws QException + { + QInstance qInstance = QContext.getQInstance(); + ExecuteCodeInput executeCodeInput = setupInput(qInstance, Map.of("x", 4), new SystemOutExecutionLogger()); + ExecuteCodeOutput executeCodeOutput = new ExecuteCodeOutput(); + new ExecuteCodeAction().run(executeCodeInput, executeCodeOutput); + assertEquals(16, executeCodeOutput.getOutput()); + } + + + /******************************************************************************* ** *******************************************************************************/ diff --git a/qqq-middleware-api/src/main/java/com/kingsrook/qqq/api/actions/ApiImplementation.java b/qqq-middleware-api/src/main/java/com/kingsrook/qqq/api/actions/ApiImplementation.java index ea6aa532..9abe151e 100644 --- a/qqq-middleware-api/src/main/java/com/kingsrook/qqq/api/actions/ApiImplementation.java +++ b/qqq-middleware-api/src/main/java/com/kingsrook/qqq/api/actions/ApiImplementation.java @@ -986,9 +986,16 @@ public class ApiImplementation { String[] ids = paramMap.get(idParam).split(","); - QTableMetaData table = QContext.getQInstance().getTable(process.getTableName()); - QQueryFilter filter = new QQueryFilter(new QFilterCriteria(table.getPrimaryKeyField(), IN, Arrays.asList(ids))); - runProcessInput.setCallback(getCallback(filter)); + if(StringUtils.hasContent(process.getTableName())) + { + QTableMetaData table = QContext.getQInstance().getTable(process.getTableName()); + QQueryFilter filter = new QQueryFilter(new QFilterCriteria(table.getPrimaryKeyField(), IN, Arrays.asList(ids))); + runProcessInput.setCallback(getProcessCallback(filter)); + } + else + { + runProcessInput.addValue(idParam, paramMap.get(idParam)); + } } } @@ -1517,7 +1524,7 @@ public class ApiImplementation /******************************************************************************* ** *******************************************************************************/ - private static QProcessCallback getCallback(QQueryFilter filter) + public static QProcessCallback getProcessCallback(QQueryFilter filter) { return new QProcessCallback() {