mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +00:00
QQQ-21 adding break/skip/fail options for frontendSteps in runProcessAction; adding viewFields & recordsList fields to frontend steps
This commit is contained in:
@ -35,6 +35,7 @@ import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepResu
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessRequest;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessResult;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.state.InMemoryStateProvider;
|
||||
@ -86,30 +87,53 @@ public class RunProcessAction
|
||||
List<QStepMetaData> stepList = getAvailableStepList(process, runProcessRequest);
|
||||
try
|
||||
{
|
||||
STEP_LOOP:
|
||||
for(QStepMetaData step : stepList)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if the caller requested to only run backend steps, then break if this isn't a backend step //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if(runProcessRequest.getBackendOnly())
|
||||
if(step instanceof QFrontendStepMetaData)
|
||||
{
|
||||
if(!(step instanceof QBackendStepMetaData))
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Handle what to do with frontend steps, per request setting //
|
||||
////////////////////////////////////////////////////////////////
|
||||
switch(runProcessRequest.getFrontendStepBehavior())
|
||||
{
|
||||
LOG.info("Breaking process [" + process.getName() + "] at first non-backend step (as requested by caller): " + step.getName());
|
||||
processState.setNextStepName(step.getName());
|
||||
break;
|
||||
case BREAK ->
|
||||
{
|
||||
LOG.info("Breaking process [" + process.getName() + "] at frontend step (as requested by caller): " + step.getName());
|
||||
processState.setNextStepName(step.getName());
|
||||
break STEP_LOOP;
|
||||
}
|
||||
case SKIP ->
|
||||
{
|
||||
LOG.info("Skipping frontend step [" + step.getName() + "] in process [" + process.getName() + "] (as requested by caller)");
|
||||
processState.setNextStepName(step.getName());
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// much less error prone in case this code changes in the future... //
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// noinspection UnnecessaryContinue
|
||||
continue;
|
||||
}
|
||||
case FAIL ->
|
||||
{
|
||||
LOG.info("Throwing error for frontend step [" + step.getName() + "] in process [" + process.getName() + "] (as requested by caller)");
|
||||
throw (new QException("Failing process at step " + step.getName() + " (as requested, to fail on frontend steps)"));
|
||||
}
|
||||
default -> throw new IllegalStateException("Unexpected value: " + runProcessRequest.getFrontendStepBehavior());
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
// run the step, based on its type //
|
||||
/////////////////////////////////////
|
||||
if(step instanceof QBackendStepMetaData backendStepMetaData)
|
||||
else if(step instanceof QBackendStepMetaData backendStepMetaData)
|
||||
{
|
||||
///////////////////////
|
||||
// Run backend steps //
|
||||
///////////////////////
|
||||
runBackendStep(runProcessRequest, process, runProcessResult, stateKey, backendStepMetaData, processState);
|
||||
}
|
||||
else
|
||||
{
|
||||
//////////////////////////////////////////////////
|
||||
// in case we have a different step type, throw //
|
||||
//////////////////////////////////////////////////
|
||||
throw (new QException("Unsure how to run a step of type: " + step.getClass().getName()));
|
||||
}
|
||||
}
|
||||
|
@ -122,9 +122,20 @@ public class QInstanceEnricher
|
||||
step.getInputFields().forEach(this::enrich);
|
||||
step.getOutputFields().forEach(this::enrich);
|
||||
|
||||
if (step instanceof QFrontendStepMetaData)
|
||||
if (step instanceof QFrontendStepMetaData frontendStepMetaData)
|
||||
{
|
||||
((QFrontendStepMetaData)step).getFormFields().forEach(this::enrich);
|
||||
if(frontendStepMetaData.getFormFields() != null)
|
||||
{
|
||||
frontendStepMetaData.getFormFields().forEach(this::enrich);
|
||||
}
|
||||
if(frontendStepMetaData.getViewFields() != null)
|
||||
{
|
||||
frontendStepMetaData.getViewFields().forEach(this::enrich);
|
||||
}
|
||||
if(frontendStepMetaData.getRecordListFields() != null)
|
||||
{
|
||||
frontendStepMetaData.getRecordListFields().forEach(this::enrich);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,8 @@ import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.interfaces.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepRequest;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepResult;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -35,16 +37,26 @@ import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepResu
|
||||
*******************************************************************************/
|
||||
public class MockBackendStep implements BackendStep
|
||||
{
|
||||
private static final Logger LOG = LogManager.getLogger(MockBackendStep.class);
|
||||
|
||||
public static final String FIELD_GREETING_PREFIX = "greetingPrefix";
|
||||
public static final String FIELD_GREETING_SUFFIX = "greetingSuffix";
|
||||
public static final String FIELD_MOCK_VALUE = "mockValue";
|
||||
public static final String MOCK_VALUE = "You so silly";
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void run(RunBackendStepRequest runBackendStepRequest, RunBackendStepResult runBackendStepResult) throws QException
|
||||
{
|
||||
runBackendStepResult.getRecords().forEach(r -> r.setValue("mockValue", "Ha ha!"));
|
||||
runBackendStepResult.getRecords().forEach(r ->
|
||||
{
|
||||
r.setValue(FIELD_MOCK_VALUE, "Ha ha!");
|
||||
LOG.info("We are mocking {}: {}", r.getValueString("firstName"), r.getValue(FIELD_MOCK_VALUE));
|
||||
});
|
||||
|
||||
runBackendStepResult.setValues(runBackendStepRequest.getValues());
|
||||
runBackendStepResult.addValue("mockValue", "You so silly");
|
||||
runBackendStepResult.addValue(FIELD_MOCK_VALUE, MOCK_VALUE);
|
||||
|
||||
/////////////////////////////////
|
||||
// mock the "greet" process... //
|
||||
|
@ -39,13 +39,25 @@ import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||
*******************************************************************************/
|
||||
public class RunProcessRequest extends AbstractQRequest
|
||||
{
|
||||
private String processName;
|
||||
private QProcessCallback callback;
|
||||
private ProcessState processState;
|
||||
private boolean backendOnly = false;
|
||||
private String startAfterStep;
|
||||
private String processUUID;
|
||||
private AsyncJobCallback asyncJobCallback;
|
||||
private String processName;
|
||||
private QProcessCallback callback;
|
||||
private ProcessState processState;
|
||||
private FrontendStepBehavior frontendStepBehavior = FrontendStepBehavior.BREAK;
|
||||
private String startAfterStep;
|
||||
private String processUUID;
|
||||
private AsyncJobCallback asyncJobCallback;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public enum FrontendStepBehavior
|
||||
{
|
||||
BREAK,
|
||||
SKIP,
|
||||
FAIL
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -285,21 +297,23 @@ public class RunProcessRequest extends AbstractQRequest
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for frontendStepBehavior
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setBackendOnly(boolean backendOnly)
|
||||
public FrontendStepBehavior getFrontendStepBehavior()
|
||||
{
|
||||
this.backendOnly = backendOnly;
|
||||
return frontendStepBehavior;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for frontendStepBehavior
|
||||
**
|
||||
*******************************************************************************/
|
||||
public boolean getBackendOnly()
|
||||
public void setFrontendStepBehavior(FrontendStepBehavior frontendStepBehavior)
|
||||
{
|
||||
return backendOnly;
|
||||
this.frontendStepBehavior = frontendStepBehavior;
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,6 +35,8 @@ import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData;
|
||||
public class QFrontendStepMetaData extends QStepMetaData
|
||||
{
|
||||
private List<QFieldMetaData> formFields;
|
||||
private List<QFieldMetaData> viewFields;
|
||||
private List<QFieldMetaData> recordListFields;
|
||||
|
||||
|
||||
|
||||
@ -88,6 +90,106 @@ public class QFrontendStepMetaData extends QStepMetaData
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for viewFields
|
||||
**
|
||||
*******************************************************************************/
|
||||
public List<QFieldMetaData> getViewFields()
|
||||
{
|
||||
return viewFields;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for viewFields
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setViewFields(List<QFieldMetaData> viewFields)
|
||||
{
|
||||
this.viewFields = viewFields;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** fluent setter to add a single view field
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QFrontendStepMetaData withViewField(QFieldMetaData viewField)
|
||||
{
|
||||
if(this.viewFields == null)
|
||||
{
|
||||
this.viewFields = new ArrayList<>();
|
||||
}
|
||||
this.viewFields.add(viewField);
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** fluent setter for viewFields
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QFrontendStepMetaData withViewFields(List<QFieldMetaData> viewFields)
|
||||
{
|
||||
this.viewFields = viewFields;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for recordListFields
|
||||
**
|
||||
*******************************************************************************/
|
||||
public List<QFieldMetaData> getRecordListFields()
|
||||
{
|
||||
return recordListFields;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for recordListFields
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setRecordListFields(List<QFieldMetaData> recordListFields)
|
||||
{
|
||||
this.recordListFields = recordListFields;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** fluent setter to add a single recordList field
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QFrontendStepMetaData withRecordListField(QFieldMetaData recordListField)
|
||||
{
|
||||
if(this.recordListFields == null)
|
||||
{
|
||||
this.recordListFields = new ArrayList<>();
|
||||
}
|
||||
this.recordListFields.add(recordListField);
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** fluent setter for recordListFields
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QFrontendStepMetaData withRecordListFields(List<QFieldMetaData> recordListFields)
|
||||
{
|
||||
this.recordListFields = recordListFields;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** fluent setter for name
|
||||
**
|
||||
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.processes.implementations;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.interfaces.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepRequest;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepResult;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QCodeReference;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QCodeType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QCodeUsage;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionInputMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QRecordListMetaData;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Function body to take care of loading the initial records to be used by a
|
||||
** process.
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class LoadInitialRecordsStep implements BackendStep
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public void run(RunBackendStepRequest runBackendStepRequest, RunBackendStepResult runBackendStepResult) throws QException
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// actually, this is a no-op... we Just need a backendStep to be the first step in the process //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static QBackendStepMetaData defineMetaData(String tableName)
|
||||
{
|
||||
return (new QBackendStepMetaData()
|
||||
.withName("loadInitialRecords")
|
||||
.withCode(new QCodeReference()
|
||||
.withName(LoadInitialRecordsStep.class.getName())
|
||||
.withCodeType(QCodeType.JAVA)
|
||||
.withCodeUsage(QCodeUsage.BACKEND_STEP))
|
||||
.withInputData(new QFunctionInputMetaData()
|
||||
.withRecordListMetaData(new QRecordListMetaData()
|
||||
.withTableName(tableName))));
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -29,6 +29,7 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import com.kingsrook.qqq.backend.core.callbacks.QProcessCallback;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.interfaces.mock.MockBackendStep;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessRequest;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessResult;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.query.QQueryFilter;
|
||||
@ -37,10 +38,12 @@ import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -75,7 +78,7 @@ public class RunProcessTest
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testBackendOnly() throws QException
|
||||
public void testBreakOnFrontendSteps() throws QException
|
||||
{
|
||||
TestCallback callback = new TestCallback();
|
||||
QInstance instance = TestUtils.defineInstance();
|
||||
@ -84,7 +87,7 @@ public class RunProcessTest
|
||||
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setProcessName(processName);
|
||||
request.setBackendOnly(true);
|
||||
request.setFrontendStepBehavior(RunProcessRequest.FrontendStepBehavior.BREAK);
|
||||
request.setCallback(callback);
|
||||
RunProcessResult result0 = new RunProcessAction().execute(request);
|
||||
|
||||
@ -114,6 +117,58 @@ public class RunProcessTest
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testSkipFrontendSteps() throws QException
|
||||
{
|
||||
TestCallback callback = new TestCallback();
|
||||
QInstance instance = TestUtils.defineInstance();
|
||||
RunProcessRequest request = new RunProcessRequest(instance);
|
||||
String processName = TestUtils.PROCESS_NAME_GREET_PEOPLE_INTERACTIVE;
|
||||
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setProcessName(processName);
|
||||
request.setFrontendStepBehavior(RunProcessRequest.FrontendStepBehavior.SKIP);
|
||||
request.setCallback(callback);
|
||||
|
||||
RunProcessResult runProcessResult = new RunProcessAction().execute(request);
|
||||
assertTrue(runProcessResult.getException().isEmpty());
|
||||
assertEquals(MockBackendStep.MOCK_VALUE, runProcessResult.getValues().get(MockBackendStep.FIELD_MOCK_VALUE));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
public void testFailOnFrontendSteps()
|
||||
{
|
||||
TestCallback callback = new TestCallback();
|
||||
QInstance instance = TestUtils.defineInstance();
|
||||
RunProcessRequest request = new RunProcessRequest(instance);
|
||||
String processName = TestUtils.PROCESS_NAME_GREET_PEOPLE_INTERACTIVE;
|
||||
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setProcessName(processName);
|
||||
request.setFrontendStepBehavior(RunProcessRequest.FrontendStepBehavior.FAIL);
|
||||
request.setCallback(callback);
|
||||
|
||||
try
|
||||
{
|
||||
new RunProcessAction().execute(request);
|
||||
fail("This should have thrown...");
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
assertTrue(e.getMessage().contains("fail on frontend steps"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
Reference in New Issue
Block a user