Skip to content

Commit

Permalink
feat(failure): define scope and context on failures (#3247)
Browse files Browse the repository at this point in the history
  • Loading branch information
rbioteau authored Nov 19, 2024
1 parent c6b656a commit 2bb2812
Show file tree
Hide file tree
Showing 56 changed files with 1,177 additions and 426 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.bonitasoft.engine.bpm.process.ProcessDeploymentInfo;
import org.bonitasoft.engine.bpm.process.ProcessInstance;
import org.bonitasoft.engine.bpm.process.impl.ProcessDefinitionBuilder;
import org.bonitasoft.engine.commons.exceptions.ScopedException;
import org.bonitasoft.engine.expression.ExpressionBuilder;
import org.bonitasoft.engine.operation.LeftOperandBuilder;
import org.bonitasoft.engine.operation.OperatorType;
Expand Down Expand Up @@ -73,8 +74,13 @@ public void create_a_failure_on_flownode_operation_exception() throws Exception
var failures = serviceAccessor.getTransactionService()
.executeInTransaction(() -> failureService.getFlowNodeFailures(failFlowNodeInstance.getId(), 5));
assertThat(failures).hasSize(1);
assertThat(failures.get(0).getErrorMessage())
.isEqualTo("java.lang.RuntimeException: Failed !");
var failure = failures.get(0);
assertThat(failure.getScope())
.isEqualTo(ScopedException.OPERATION);
assertThat(failure.getContext())
.isEqualTo("expression::my-failing-script");
assertThat(failure.getErrorMessage())
.isEqualTo("RuntimeException: Failed !");
disableAndDeleteProcess(processDefinition);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.bonitasoft.engine.bpm.connector.ConnectorState;
import org.bonitasoft.engine.builder.BuilderFactory;
import org.bonitasoft.engine.commons.exceptions.SBonitaException;
import org.bonitasoft.engine.commons.exceptions.ScopedException;
import org.bonitasoft.engine.core.connector.ConnectorInstanceService;
import org.bonitasoft.engine.core.data.instance.TransientDataService;
import org.bonitasoft.engine.core.expression.control.api.ExpressionResolverService;
Expand Down Expand Up @@ -762,7 +763,7 @@ void warningWhenTransientDataWithNullValue() {
}

private void createDataForProcess(final List<SDataInstance> sDataInstances)
throws SDataInstanceException, SFlowNodeNotFoundException, SFlowNodeReadException {
throws SDataInstanceException {
if (!sDataInstances.isEmpty()) {
for (final SDataInstance sDataInstance : sDataInstances) {
dataInstanceService.createDataInstance(sDataInstance);
Expand Down Expand Up @@ -874,25 +875,33 @@ private boolean createDataInstances(final SActivityDefinition activityDefinition
throws SActivityStateExecutionException {
final List<SDataDefinition> sDataDefinitions = activityDefinition.getSDataDefinitions();
final SLoopCharacteristics loopCharacteristics = activityDefinition.getLoopCharacteristics();
try {
if (loopCharacteristics instanceof SMultiInstanceLoopCharacteristics
&& (((SMultiInstanceLoopCharacteristics) loopCharacteristics).getDataInputItemRef() != null
|| ((SMultiInstanceLoopCharacteristics) loopCharacteristics)
.getDataOutputItemRef() != null)) {

if (loopCharacteristics instanceof SMultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics
&& (multiInstanceLoopCharacteristics.getDataInputItemRef() != null
|| multiInstanceLoopCharacteristics.getDataOutputItemRef() != null)) {
try {
createDataInstancesForMultiInstance(activityDefinition, flowNodeInstance, expressionContext);
} else {
} catch (final SBonitaException e) {
throw new SActivityStateExecutionException(
"Failed to initialize multi instance variables of " + flowNodeInstance,
ScopedException.ITERATION, e);
}
} else {
try {
createDataInstances(sDataDefinitions, flowNodeInstance.getId(), DataInstanceContainer.ACTIVITY_INSTANCE,
expressionContext);
} catch (final SBonitaException e) {
throw new SActivityStateExecutionException("Failed to initialize variables of " + flowNodeInstance,
ScopedException.DATA, e);
}
if (!sDataDefinitions.isEmpty() && log.isDebugEnabled()) {
final String message = "Initialized variables for flow node"
+ LogMessageBuilder.buildFlowNodeContextMessage(flowNodeInstance);
log.debug(message);
}
return sDataDefinitions.size() > 0;
} catch (final SBonitaException e) {
throw new SActivityStateExecutionException(e);
}
if (!sDataDefinitions.isEmpty() && log.isDebugEnabled()) {
final String message = "Initialized variables for flow node"
+ LogMessageBuilder.buildFlowNodeContextMessage(flowNodeInstance);
log.debug(message);
}
return !sDataDefinitions.isEmpty();

}

protected void createDataInstancesForMultiInstance(final SActivityDefinition activityDefinition,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.bonitasoft.engine.commons.exceptions.SBonitaException;
import org.bonitasoft.engine.commons.exceptions.SObjectCreationException;
import org.bonitasoft.engine.commons.exceptions.SObjectModificationException;
import org.bonitasoft.engine.commons.exceptions.ScopedException;
import org.bonitasoft.engine.core.connector.ConnectorInstanceService;
import org.bonitasoft.engine.core.connector.ConnectorResult;
import org.bonitasoft.engine.core.connector.ConnectorService;
Expand Down Expand Up @@ -245,7 +246,9 @@ public boolean registerConnectorsToExecute(final SProcessDefinition processDefin
workService.registerWork(workFactory.createExecuteConnectorOfProcessDescriptor(
processDefinitionId, sProcessInstance.getId(),
sProcessInstance.getRootProcessInstanceId(), nextConnectorInstance.getId(),
sConnectorDefinition.getName(), activationEvent,
sConnectorDefinition.getConnectorId(),
sConnectorDefinition.getName(),
activationEvent,
selectorForConnectorOnEnter));
return true;
}
Expand Down Expand Up @@ -404,30 +407,45 @@ protected boolean initialize(final long userId, final SProcessDefinition sProces
final List<ConnectorDefinitionWithInputValues> connectors,
final FlowNodeSelector selectorForConnectorOnEnter, final Map<String, Serializable> processInputs)
throws SBonitaException {

SExpressionContext expressionContext = createExpressionsContextForProcessInstance(sProcessDefinition,
sProcessInstance);
operations = operations != null ? new ArrayList<>(operations) : Collections.emptyList();

storeProcessInstantiationInputs(sProcessInstance.getId(), processInputs);
operations = operations != null ? new ArrayList<>(operations) : Collections.emptyList();
try {
storeProcessInstantiationInputs(sProcessInstance.getId(), processInputs);

// Create SDataInstances
bpmInstancesCreator.createDataInstances(sProcessInstance, processContainer, sProcessDefinition,
expressionContext, operations, context,
expressionContextToEvaluateOperations);
// Create SDataInstances
bpmInstancesCreator.createDataInstances(sProcessInstance, processContainer, sProcessDefinition,
expressionContext, operations, context,
expressionContextToEvaluateOperations);

initializeBusinessData(processContainer, sProcessInstance, expressionContext);
initializeStringIndexes(sProcessInstance, sProcessDefinition, processContainer);
initializeBusinessData(processContainer, sProcessInstance, expressionContext);
initializeStringIndexes(sProcessInstance, sProcessDefinition, processContainer);

createDocuments(sProcessDefinition, processContainer, sProcessInstance, userId, expressionContext, context);
createDocumentLists(processContainer, sProcessInstance, userId, expressionContext, context);
createDocuments(sProcessDefinition, processContainer, sProcessInstance, userId, expressionContext, context);
createDocumentLists(processContainer, sProcessInstance, userId, expressionContext, context);
} catch (SBonitaException e) {
e.setScope(ScopedException.DATA);
throw e;
}
if (connectors != null) {
//these are set only when start process through the command ExecuteActionsAndStartInstanceExt
executeConnectors(sProcessDefinition, sProcessInstance, connectors);
try {
executeConnectors(sProcessDefinition, sProcessInstance, connectors);
} catch (SBonitaException e) {
e.setScope(ScopedException.CONNECTOR);
throw e;
}
}
// operations given to the startProcess method of the API or by command, not operations of the process definition
executeOperations(operations, context, expressionContext, expressionContextToEvaluateOperations,
sProcessInstance);
try {
executeOperations(operations, context, expressionContext, expressionContextToEvaluateOperations,
sProcessInstance);
} catch (SBonitaException e) {
// Data mapping of call activity
e.setScope(ScopedException.DATA);
throw e;
}

// Create connectors
bpmInstancesCreator.createConnectorInstances(sProcessInstance, processContainer.getConnectors(),
Expand Down
Loading

0 comments on commit 2bb2812

Please sign in to comment.