Skip to content

Commit b73b03c

Browse files
committed
[KOGITO-9811] Resolving timer on runtime
1 parent 7f148ed commit b73b03c

File tree

4 files changed

+46
-15
lines changed

4 files changed

+46
-15
lines changed

jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/StateBasedNodeInstance.java

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,11 @@
3434
import org.jbpm.process.core.timer.Timer;
3535
import org.jbpm.process.instance.InternalProcessRuntime;
3636
import org.jbpm.process.instance.impl.Action;
37+
import org.jbpm.ruleflow.core.Metadata;
3738
import org.jbpm.util.ContextFactory;
3839
import org.jbpm.workflow.core.DroolsAction;
40+
import org.jbpm.workflow.core.WorkflowProcess;
41+
import org.jbpm.workflow.core.impl.NodeImpl;
3942
import org.jbpm.workflow.core.node.StateBasedNode;
4043
import org.jbpm.workflow.instance.impl.ExtendedNodeInstanceImpl;
4144
import org.jbpm.workflow.instance.impl.WorkflowProcessInstanceImpl;
@@ -51,6 +54,8 @@
5154
import org.kie.kogito.jobs.ExpirationTime;
5255
import org.kie.kogito.jobs.JobsService;
5356
import org.kie.kogito.jobs.ProcessInstanceJobDescription;
57+
import org.kie.kogito.process.expr.Expression;
58+
import org.kie.kogito.process.expr.ExpressionHandlerFactory;
5459
import org.kie.kogito.timer.TimerInstance;
5560
import org.slf4j.Logger;
5661
import org.slf4j.LoggerFactory;
@@ -68,6 +73,8 @@ public abstract class StateBasedNodeInstance extends ExtendedNodeInstanceImpl im
6873

6974
private Map<String, String> timerInstancesReference;
7075

76+
private transient KogitoProcessContext context;
77+
7178
public StateBasedNode getEventBasedNode() {
7279
return (StateBasedNode) getNode();
7380
}
@@ -144,8 +151,8 @@ protected ExpirationTime createTimerInstance(Timer timer) {
144151
switch (timer.getTimeType()) {
145152
case Timer.TIME_CYCLE:
146153

147-
String tempDelay = resolveExpression(timer.getDelay());
148-
String tempPeriod = resolveExpression(timer.getPeriod());
154+
String tempDelay = resolveTimerExpression(timer.getDelay());
155+
String tempPeriod = resolveTimerExpression(timer.getPeriod());
149156
if (DateTimeUtils.isRepeatable(tempDelay)) {
150157
String[] values = DateTimeUtils.parseISORepeatable(tempDelay);
151158
String tempRepeatLimit = values[0];
@@ -174,7 +181,7 @@ protected ExpirationTime createTimerInstance(Timer timer) {
174181
}
175182

176183
case Timer.TIME_DURATION:
177-
delay = resolveExpression(timer.getDelay());
184+
delay = resolveTimerExpression(timer.getDelay());
178185

179186
return DurationExpirationTime.repeat(businessCalendar.calculateBusinessTimeAsDuration(delay));
180187
case Timer.TIME_DATE:
@@ -196,14 +203,14 @@ protected ExpirationTime configureTimerInstance(Timer timer) {
196203
case Timer.TIME_CYCLE:
197204
if (timer.getPeriod() != null) {
198205

199-
long actualDelay = DateTimeUtils.parseDuration(resolveExpression(timer.getDelay()));
206+
long actualDelay = DateTimeUtils.parseDuration(resolveTimerExpression(timer.getDelay()));
200207
if (timer.getPeriod() == null) {
201208
return DurationExpirationTime.repeat(actualDelay, actualDelay, Integer.MAX_VALUE);
202209
} else {
203-
return DurationExpirationTime.repeat(actualDelay, DateTimeUtils.parseDuration(resolveExpression(timer.getPeriod())), Integer.MAX_VALUE);
210+
return DurationExpirationTime.repeat(actualDelay, DateTimeUtils.parseDuration(resolveTimerExpression(timer.getPeriod())), Integer.MAX_VALUE);
204211
}
205212
} else {
206-
String resolvedDelay = resolveExpression(timer.getDelay());
213+
String resolvedDelay = resolveTimerExpression(timer.getDelay());
207214

208215
// when using ISO date/time period is not set
209216
long[] repeatValues = null;
@@ -233,7 +240,7 @@ protected ExpirationTime configureTimerInstance(Timer timer) {
233240
duration = DateTimeUtils.parseDuration(timer.getDelay());
234241
} catch (RuntimeException e) {
235242
// cannot parse delay, trying to interpret it
236-
s = resolveExpression(timer.getDelay());
243+
s = resolveTimerExpression(timer.getDelay());
237244
duration = DateTimeUtils.parseDuration(s);
238245
}
239246
return DurationExpirationTime.after(duration);
@@ -243,13 +250,29 @@ protected ExpirationTime configureTimerInstance(Timer timer) {
243250
return ExactExpirationTime.of(timer.getDate());
244251
} catch (RuntimeException e) {
245252
// cannot parse delay, trying to interpret it
246-
s = resolveExpression(timer.getDate());
253+
s = resolveTimerExpression(timer.getDate());
247254
return ExactExpirationTime.of(s);
248255
}
249256
}
250257
throw new UnsupportedOperationException("Not supported timer definition");
251258
}
252259

260+
private String resolveTimerExpression(String expression) {
261+
if (!isExpression(expression)) {
262+
WorkflowProcess process = ((NodeImpl) getNode()).getProcess();
263+
Expression exprObject = ExpressionHandlerFactory.get(process.getExpressionLanguage(), expression);
264+
if (exprObject.isValid()) {
265+
if (context == null) {
266+
context = ContextFactory.fromNode(this);
267+
}
268+
String varName = (String) process.getMetaData().get(Metadata.VARIABLE);
269+
Object target = varName == null ? this.getProcessInstance().getVariables() : context.getVariable(varName);
270+
return exprObject.eval(target, String.class, context);
271+
}
272+
}
273+
return resolveExpression(expression);
274+
}
275+
253276
protected void handleSLAViolation() {
254277
if (slaCompliance == KogitoProcessInstance.SLA_PENDING) {
255278
InternalProcessRuntime processRuntime = ((InternalProcessRuntime) getProcessInstance().getKnowledgeRuntime().getProcessRuntime());

kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/parser/ServerlessWorkflowParser.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ private GeneratedInfo<KogitoWorkflowProcess> parseProcess() {
129129
DEFAULT_PACKAGE) : DEFAULT_PACKAGE)
130130
.visibility("Public")
131131
.expressionLanguage(workflow.getExpressionLang())
132+
.metaData(Metadata.VARIABLE, DEFAULT_WORKFLOW_VAR)
132133
.variable(DEFAULT_WORKFLOW_VAR, new ObjectDataType(JsonNode.class), ObjectMapperFactory.listenerAware().createObjectNode())
133134
.type(KogitoWorkflowProcess.SW_TYPE);
134135
ParserContext parserContext =

kogito-serverless-workflow/kogito-serverless-workflow-builder/src/main/java/org/kie/kogito/serverless/workflow/utils/TimeoutsConfigResolver.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import java.time.Duration;
2222
import java.time.format.DateTimeParseException;
2323

24+
import org.kie.kogito.process.expr.ExpressionHandlerFactory;
25+
2426
import io.serverlessworkflow.api.Workflow;
2527
import io.serverlessworkflow.api.interfaces.State;
2628
import io.serverlessworkflow.api.timeouts.TimeoutsDefinition;
@@ -45,26 +47,30 @@ public static String resolveEventTimeout(State state, Workflow workflow) {
4547
String.format(INVALID_EVENT_TIMEOUT_FOR_STATE_ERROR,
4648
timeouts.getEventTimeout(),
4749
state.getName(),
48-
workflow.getName()));
50+
workflow.getName()),
51+
workflow.getExpressionLang());
4952
return timeouts.getEventTimeout();
5053
} else {
5154
timeouts = workflow.getTimeouts();
5255
if (timeouts != null && timeouts.getEventTimeout() != null) {
5356
validateDuration(timeouts.getEventTimeout(),
5457
String.format(INVALID_EVENT_TIMEOUT_FOR_WORKFLOW_ERROR,
5558
timeouts.getEventTimeout(),
56-
workflow.getName()));
59+
workflow.getName()),
60+
workflow.getExpressionLang());
5761
return timeouts.getEventTimeout();
5862
}
5963
}
6064
return null;
6165
}
6266

63-
private static void validateDuration(String value, String message) {
64-
try {
65-
Duration.parse(value);
66-
} catch (DateTimeParseException e) {
67-
throw new IllegalArgumentException(message, e);
67+
private static void validateDuration(String value, String message, String exprLanguage) {
68+
if (!ExpressionHandlerFactory.get(exprLanguage, value).isValid()) {
69+
try {
70+
Duration.parse(value);
71+
} catch (DateTimeParseException e) {
72+
throw new IllegalArgumentException(message, e);
73+
}
6874
}
6975
}
7076
}

kogito-serverless-workflow/kogito-serverless-workflow-builder/src/test/java/org/kie/kogito/serverless/workflow/utils/TimeoutsConfigResolverTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ private static State mockState(String name, String eventTimeout) {
9797

9898
private static Workflow mockWorkflow(String name) {
9999
Workflow workflow = mock(Workflow.class);
100+
doReturn("jq").when(workflow).getExpressionLang();
100101
doReturn(name).when(workflow).getName();
101102
return workflow;
102103
}

0 commit comments

Comments
 (0)