Skip to content

Commit

Permalink
[Fix apache#3475] Parsing the errorMessage metadata keys in end nodes (
Browse files Browse the repository at this point in the history
…apache#3491)

* [Fix apache#3475] Parsing the errorMessage metadata keys in end nodes

* [Fix apache#3475] Do not abort process instance

* [Fix apache#3475] Adding IT test
  • Loading branch information
fjtirado authored and rgdoliveira committed May 7, 2024
1 parent 54ad37c commit 0a93241
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.Collection;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;

Expand Down Expand Up @@ -51,6 +52,7 @@
import org.kie.kogito.serverless.workflow.parser.ServerlessWorkflowParser;
import org.kie.kogito.serverless.workflow.suppliers.CollectorActionSupplier;
import org.kie.kogito.serverless.workflow.suppliers.CompensationActionSupplier;
import org.kie.kogito.serverless.workflow.suppliers.ErrorExpressionActionSupplier;
import org.kie.kogito.serverless.workflow.suppliers.ExpressionActionSupplier;
import org.kie.kogito.serverless.workflow.suppliers.MergeActionSupplier;
import org.kie.kogito.serverless.workflow.suppliers.ProduceEventActionSupplier;
Expand Down Expand Up @@ -517,15 +519,26 @@ protected final void createTimerNode(RuleFlowNodeContainerFactory<?, ?> factory,
WorkflowElementIdentifier id = parserContext.newId();
EndNodeFactory<?> nodeFactory = factory.endNode(id);
NodeFactory<?, ?> startNode = nodeFactory;

List<ProduceEvent> produceEvents = end.getProduceEvents();
if (produceEvents != null && !produceEvents.isEmpty()) {
startNode = handleProduceEvents(factory, nodeFactory, produceEvents);
}

Map<String, String> metadata = state.getMetadata();
if (metadata != null) {
String errorMessage = metadata.get("errorMessage");
if (errorMessage != null && !errorMessage.isBlank()) {
NodeFactory<?, ?> errorMessageNode =
factory.actionNode(parserContext.newId()).action(new ErrorExpressionActionSupplier(workflow.getExpressionLang(), errorMessage, SWFConstants.DEFAULT_WORKFLOW_VAR));
connect(errorMessageNode, startNode);
startNode = errorMessageNode;
}
}
nodeFactory.terminate(end.isTerminate());
return startNode;
}

@SuppressWarnings("squid:S1452")
private NodeFactory<?, ?> compensationEvent(RuleFlowNodeContainerFactory<?, ?> factory, NodeFactory<?, ?> sourceFactory) {
WorkflowElementIdentifier eventId = parserContext.newId();
NodeFactory<?, ?> compensationNode =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* 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.kie.kogito.serverless.workflow.suppliers;

import org.jbpm.compiler.canonical.ExpressionSupplier;
import org.jbpm.compiler.canonical.ProcessMetaData;
import org.jbpm.compiler.canonical.descriptors.ExpressionUtils;
import org.kie.kogito.internal.process.runtime.KogitoNode;
import org.kie.kogito.serverless.workflow.actions.ErrorExpressionAction;

import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.ObjectCreationExpr;

public class ErrorExpressionActionSupplier extends ErrorExpressionAction implements ExpressionSupplier {

private ObjectCreationExpr expression;

public ErrorExpressionActionSupplier(String lang, String expr, String inputVar) {
super(lang, expr, inputVar);
this.expression = ExpressionUtils.getObjectCreationExpr(ErrorExpressionAction.class, lang, expr, inputVar);
}

@Override
public Expression get(KogitoNode node, ProcessMetaData metadata) {
return expression;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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.kie.kogito.serverless.workflow.actions;

import org.jbpm.process.instance.ProcessInstance;
import org.jbpm.workflow.instance.NodeInstance;
import org.kie.kogito.internal.process.runtime.KogitoProcessContext;

import com.fasterxml.jackson.databind.JsonNode;

public class ErrorExpressionAction extends BaseExpressionAction {

public ErrorExpressionAction(String lang, String expr, String inputVar) {
super(lang, expr, inputVar);
}

public void execute(KogitoProcessContext context) throws Exception {
if (expr.isValid()) {
JsonNode error = evaluate(context, JsonNode.class);
if (!error.isNull() && error.isTextual()) {
String errorStr = error.asText();
if (!errorStr.isBlank()) {
setError(context, errorStr);
}
}
} else {
setError(context, expr.toString());
}
}

private void setError(KogitoProcessContext context, String error) {
((ProcessInstance) context.getProcessInstance()).setErrorState((NodeInstance) context.getNodeInstance(), new IllegalArgumentException(error));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"id": "errorWithMetadata",
"version": "1.0",
"name": "Workflow Error example with metadata",
"description": "An example of how to abort a workflow with error given a condition",
"start": "checkEven",
"states": [
{
"name": "checkEven",
"type": "operation",
"actions": [],
"end" : true,
"metadata": {
"errorMessage": "if .number % 2 != 0 then \"Is Odd number!!!!\" else null end"
}
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,25 @@ private void innerErrorRest(String workflowId) {
.body("workflowdata.numberType", is("even"))
.body("workflowdata.perfect", is(false));
}

@Test
public void testErrorWithMetadata() {
given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
.body("{\"number\" : 12342}")
.when()
.post("/errorWithMetadata")
.then()
.statusCode(201);

given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
.body("{\"number\" : 12341}")
.when()
.post("/errorWithMetadata")
.then()
.statusCode(400);
}
}

0 comments on commit 0a93241

Please sign in to comment.