Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DecisionInstanceID to API response for evaluating a decision #4915

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,20 @@ public interface DmnDecisionResult extends List<DmnDecisionResultEntries>, Seria
*/
<T extends TypedValue> T getSingleEntryTyped();

/**
* Returns the value of decisionInstanceId that's part of DMN decision
* evaluation
*
* @return the decisionInstanceId generated Returns null for a standalone dmn
* engine
*/
String getDmnDecisionInstanceId();

/**
* Set generated decisionInstanceId that's generated part of DMN evaluation
*
* @param dmnDecisionInstanceId
*/
void setDmnDecisionInstanceId(String dmnDecisionInstanceId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public interface DmnEngine {
* @throws DmnEngineException
* if an error occurs during the evaluation
*
* @see #evaluateDecision(DmnDecision, VariableContext)
* @see #evaluateDecision(DmnDecision, VariableContext, String)
*/
DmnDecisionTableResult evaluateDecisionTable(DmnDecision decision, VariableContext variableContext);

Expand Down Expand Up @@ -262,6 +262,22 @@ public interface DmnEngine {
*/
DmnDecisionResult evaluateDecision(DmnDecision decision, VariableContext variableContext);

/**
* Evaluates a decision. The decision can be implemented as any kind of supported decision logic (e.g., decision table, literal expression).
*
* @param decision the {@link DmnDecision} to evaluate
* @param variableContext the variables context which is available during the evaluation
* of expressions in the table
* @param decisionInstanceId the variable that contains the decisionInstanceId for decision evaluation
* @return the {@link DmnDecisionResult} of this evaluation
*
* @throws DmnEngineException
* if the decision logic is not supported
* @throws DmnEngineException
* if an error occurs during the evaluation
*/
DmnDecisionResult evaluateDecision(DmnDecision decision, VariableContext variableContext, String decisionInstanceId);

/**
* Evaluates the decision with the given key in a DMN decision model.
* The key is the {@code id} attribute of the decision in the DMN XML file.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,9 @@ public interface DmnDecisionEvaluationEvent {
* @return the number of executed decision elements during the evaluation
*/
long getExecutedDecisionElements();

/**
* @return the decisionInstanceId generated part of DMN evaluation
*/
String getDecisionInstanceId();
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ public class DefaultDmnDecisionContext {

public DefaultDmnDecisionContext(DefaultDmnEngineConfiguration configuration) {
evaluationListeners = configuration.getDecisionEvaluationListeners();

evaluationHandlers = new HashMap<Class<? extends DmnDecisionLogic>, DmnDecisionLogicEvaluationHandler>();
evaluationHandlers.put(DmnDecisionTableImpl.class, new DecisionTableEvaluationHandler(configuration));
evaluationHandlers.put(DmnDecisionLiteralExpressionImpl.class, new DecisionLiteralExpressionEvaluationHandler(configuration));
Expand All @@ -67,7 +66,7 @@ public DefaultDmnDecisionContext(DefaultDmnEngineConfiguration configuration) {
* @param variableContext the available variable context
* @return the result of the decision evaluation
*/
public DmnDecisionResult evaluateDecision(DmnDecision decision, VariableContext variableContext) {
public DmnDecisionResult evaluateDecision(DmnDecision decision, VariableContext variableContext, String decisionInstanceId) {

if(decision.getKey() == null) {
throw LOG.unableToFindAnyDecisionTable();
Expand All @@ -90,8 +89,11 @@ public DmnDecisionResult evaluateDecision(DmnDecision decision, VariableContext
addResultToVariableContext(evaluatedResult, variableMap, evaluateDecision);
}
}

generateDecisionEvaluationEvent(evaluatedEvents);
/**
* Setting generated decisionInstanceId to the events to persist the generated value as ID for ACT_HI_DECINST table
*/
generateDecisionEvaluationEvent(evaluatedEvents, decisionInstanceId);
evaluatedResult.setDmnDecisionInstanceId(decisionInstanceId);
return evaluatedResult;
}

Expand Down Expand Up @@ -162,7 +164,7 @@ protected boolean isDecisionTableWithCollectOrRuleOrderHitPolicy(DmnDecision eva
return isDecisionTableWithCollectHitPolicy;
}

protected void generateDecisionEvaluationEvent(List<DmnDecisionLogicEvaluationEvent> evaluatedEvents) {
protected void generateDecisionEvaluationEvent(List<DmnDecisionLogicEvaluationEvent> evaluatedEvents, String decisionInstanceId) {

DmnDecisionLogicEvaluationEvent rootEvaluatedEvent = null;
DmnDecisionEvaluationEventImpl decisionEvaluationEvent = new DmnDecisionEvaluationEventImpl();
Expand All @@ -176,6 +178,8 @@ protected void generateDecisionEvaluationEvent(List<DmnDecisionLogicEvaluationEv
decisionEvaluationEvent.setDecisionResult(rootEvaluatedEvent);
decisionEvaluationEvent.setExecutedDecisionInstances(evaluatedEvents.size());
decisionEvaluationEvent.setExecutedDecisionElements(executedDecisionElements);
//Setting decisionInstanceId to the event to persist the generated id for the history event
decisionEvaluationEvent.setDecisionInstanceId(decisionInstanceId);

evaluatedEvents.remove(rootEvaluatedEvent);
decisionEvaluationEvent.setRequiredDecisionResults(evaluatedEvents);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public DmnDecisionTableResult evaluateDecisionTable(DmnDecision decision, Variab
if (decision instanceof DmnDecisionImpl && decision.isDecisionTable()) {
DefaultDmnDecisionContext decisionContext = new DefaultDmnDecisionContext(dmnEngineConfiguration);

DmnDecisionResult decisionResult = decisionContext.evaluateDecision(decision, variableContext);
DmnDecisionResult decisionResult = decisionContext.evaluateDecision(decision, variableContext, null);
return DmnDecisionTableResultImpl.wrap(decisionResult);
}
else {
Expand Down Expand Up @@ -158,13 +158,26 @@ public DmnDecisionResult evaluateDecision(DmnDecision decision, Map<String, Obje
return evaluateDecision(decision, Variables.fromMap(variables).asVariableContext());
}

public DmnDecisionResult evaluateDecision(DmnDecision decision, VariableContext variableContext, String decisionInstanceId) {
ensureNotNull("decision", decision);
ensureNotNull("variableContext", variableContext);

if (decision instanceof DmnDecisionImpl) {
DefaultDmnDecisionContext decisionContext = new DefaultDmnDecisionContext(dmnEngineConfiguration);
return decisionContext.evaluateDecision(decision, variableContext, decisionInstanceId);
}
else {
throw LOG.decisionTypeNotSupported(decision);
}
}

public DmnDecisionResult evaluateDecision(DmnDecision decision, VariableContext variableContext) {
ensureNotNull("decision", decision);
ensureNotNull("variableContext", variableContext);

if (decision instanceof DmnDecisionImpl) {
DefaultDmnDecisionContext decisionContext = new DefaultDmnDecisionContext(dmnEngineConfiguration);
return decisionContext.evaluateDecision(decision, variableContext);
return decisionContext.evaluateDecision(decision, variableContext, null);
}
else {
throw LOG.decisionTypeNotSupported(decision);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public class DmnDecisionResultImpl implements DmnDecisionResult {

protected final List<DmnDecisionResultEntries> ruleResults;

protected String dmnDecisionInstanceId;

public DmnDecisionResultImpl(List<DmnDecisionResultEntries> ruleResults) {
this.ruleResults = ruleResults;
}
Expand Down Expand Up @@ -224,6 +226,16 @@ public String toString() {
return ruleResults.toString();
}

@Override
public String getDmnDecisionInstanceId() {
return dmnDecisionInstanceId;
}

@Override
public void setDmnDecisionInstanceId(String dmnDecisionInstanceId) {
this.dmnDecisionInstanceId = dmnDecisionInstanceId;
}

protected List<DmnDecisionResultEntries> asUnmodifiableList() {
return Collections.unmodifiableList(ruleResults);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public class DmnDecisionEvaluationEventImpl implements DmnDecisionEvaluationEven
protected long executedDecisionInstances;
protected long executedDecisionElements;

protected String decisionInstanceId;

@Override
public DmnDecisionLogicEvaluationEvent getDecisionResult() {
return decisionResult;
Expand Down Expand Up @@ -66,6 +68,15 @@ public void setExecutedDecisionElements(long executedDecisionElements) {
this.executedDecisionElements = executedDecisionElements;
}

@Override
public String getDecisionInstanceId() {
return decisionInstanceId;
}

public void setDecisionInstanceId(String decisionInstanceId) {
this.decisionInstanceId = decisionInstanceId;
}

@Override
public String toString() {
DmnDecision dmnDecision = decisionResult.getDecision();
Expand All @@ -76,6 +87,7 @@ public String toString() {
", requiredDecisionResults=" + requiredDecisionResults +
", executedDecisionInstances=" + executedDecisionInstances +
", executedDecisionElements=" + executedDecisionElements +
", dmnDecisionInstanceId=" + decisionInstanceId +
'}';
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import java.io.InputStream;
import java.util.Map;
import java.util.UUID;

import org.camunda.bpm.dmn.engine.DmnDecision;
import org.camunda.bpm.dmn.engine.DmnDecisionLogic;
Expand Down Expand Up @@ -777,6 +778,20 @@ public void shouldEvaluateDecisionWithVariableContext() {
.isEqualTo(EXPECTED_OUTPUT_VALUE);
}

@Test
@DecisionResource(resource = ONE_RULE_DMN)
public void shouldEvaluateDecisionWithDecisionInstanceId() {
String decisionInstanceId = UUID.randomUUID().toString();
DmnDecisionResult results = dmnEngine.evaluateDecision(decision, createVariables().putValue("input", INPUT_VALUE).asVariableContext(), decisionInstanceId);

assertThat((String) results.getSingleEntry())
.isNotNull()
.isEqualTo(EXPECTED_OUTPUT_VALUE);
assertThat(results.getDmnDecisionInstanceId())
.isNotNull()
.isEqualTo(decisionInstanceId);
}

@Test
@DecisionResource(resource = DECISION_LITERAL_EXPRESSION_DMN)
public void shouldEvaluateDecisionLiteralExpression() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import java.util.UUID;
import org.camunda.bpm.dmn.engine.DmnDecisionResult;
import org.camunda.bpm.dmn.engine.DmnEngine;
import org.camunda.bpm.dmn.engine.DmnEngineConfiguration;
Expand Down Expand Up @@ -256,7 +256,7 @@ public void testJuelDoesNotShadowInnerProperty() {
inputs.putValue("a", mapVar);
inputs.putValue("b", "B_FROM_CONTEXT");

DmnDecisionResult result = dmnEngine.evaluateDecision(decision, inputs.asVariableContext());
DmnDecisionResult result = dmnEngine.evaluateDecision(decision, inputs.asVariableContext(), null);

assertThat((String) result.getSingleEntry()).isEqualTo("B_FROM_MAP");
}
Expand All @@ -270,10 +270,12 @@ public void testJuelResolvesListIndex() {
List<String> listVar = new ArrayList<>(1);
listVar.add("0_FROM_LIST");
inputs.putValue("a", listVar);
String decisionInstanceId = UUID.randomUUID().toString();

DmnDecisionResult result = dmnEngine.evaluateDecision(decision, inputs.asVariableContext());
DmnDecisionResult result = dmnEngine.evaluateDecision(decision, inputs.asVariableContext(), decisionInstanceId);

assertThat((String) result.getSingleEntry()).isEqualTo("0_FROM_LIST");
assertThat(result.getDmnDecisionInstanceId()).isEqualTo(decisionInstanceId);
}

protected DmnEngine createEngineWithDefaultExpressionLanguage(String expressionLanguage) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<#macro dto_macro docsUrl="">
<@lib.dto>
<@lib.property
name = "decisionInstanceId"
type = "string"
desc = "The form key." />

<@lib.property
name = "result"
type = "array"
last = true
dto = "DecisionResultDto" />
</@lib.dto>
</#macro>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<#macro dto_macro docsUrl="">
<@lib.dto>
<@lib.property
name = "result"
type = "object"
additionalProperties = true
last = true
dto = "VariableValueDto" />
</@lib.dto>
</#macro>
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<#macro endpoint_macro docsUrl="">
{
<@lib.endpointInfo
id = "evaluateDecisionByKeyWithDecisionInstanceId"
tag = "Decision Definition"
summary = "Evaluate By Key With Decision Instance Id"
desc = "Evaluates the latest version of the decision definition which belongs to no tenant.
The input values of the decision have to be supplied in the request body.
Returns decision instance id related to the evaluation" />

"parameters" : [

<@lib.parameter
name = "key"
location = "path"
type = "string"
required = true
last = true
desc = "The key of the decision definition (the latest version thereof) to be evaluated." />
],

<@lib.requestBody
mediaType = "application/json"
dto = "EvaluateDecisionDto"
examples = [ '"example-1": {
"summary": "POST /decision-definition/key/aKey/evaluate-with-id",
"value": {
"variables" : {
"amount" : { "value" : 600, "type" : "Double" },
"invoiceCategory" : { "value" : "Misc", "type" : "String" }
}
}
}'
] />

"responses" : {
<@lib.response
code = "200"
dto = "DecisionEvaluationDto"
additionalProperties = true
desc = "Request successful."
examples = ['"example-1": {
"summary": "Status 200 response",
"description": "Response for POST `/decision-definition/key/aKey/evaluate-with-id`",
"value": {
"decisionInstanceId": "aDecisionInstanceId",
"result": [{ "value" : "management", "type" : "String", "valueInfo" : null }]
}
}'] />

<@lib.response
code = "404"
dto = "ExceptionDto"
last = true
desc = "Decision definition with given key does not exist.
See the [Introduction](${docsUrl}/reference/rest/overview/#error-handling) for the error response format."/>
}
}
</#macro>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. Camunda licenses this file to you under the Apache License,
* Version 2.0; 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.camunda.bpm.engine.rest.dto.repository;

import org.camunda.bpm.engine.rest.dto.VariableValueDto;

import java.util.List;
import java.util.Map;

public class DecisionEvaluationDto {
protected String decisionInstanceId;
protected List<Map<String, VariableValueDto>> result;

public String getDecisionInstanceId() {
return decisionInstanceId;
}

public void setDecisionInstanceId(String decisionInstanceId) {
this.decisionInstanceId = decisionInstanceId;
}

public List<Map<String, VariableValueDto>> getResult() {
return result;
}

public void setResult(List<Map<String, VariableValueDto>> result) {
this.result = result;
}
}
Loading