Problem with variables in script task when using kotlin script engine

Hello community!
I’m trying to use kotlin in my script and service tasks and I have problems with variables.

My environment is:

  • camunda-bpm-platform-7.15.0
  • kotlin-scripting-jsr223-1.5.10

According to documentation Scripting | docs.camunda.org, there are special variables (execution and task), that should be accessible in scripts.
This is true while using groovy or javascript as script engine and everything works fine.

But when i try to use kotlin as script engine - I can’t access this variables.
In this case i have such errors

  • Unable to compile script: Error: ERROR Unresolved reference: execution - this happens when i simply access execution variable. For example like this println(execution) or like this println(this.execution)
  • Unable to compile script: Error: ERROR Unresolved reference: task - this happens when i simply access execution variable. For example like this println(task) or like this println(this.task)
12:57:32.280 [camundaTaskExecutor-1] ERROR org.camunda.bpm.engine.context context:{activityId=Activity_0do1frv, applicationName=application, processDefinitionId=Process_1rvr48v:18:c27fe8c1-e2e6-11eb-a184-024258ce5906, processInstanceId=ce22e1f4-e2e6-11eb-a184-024258ce5906} - ENGINE-16004 Exception while closing command context: Unable to compile script: Error: ERROR Unresolved reference: task (ScriptingHostd60d80d_Line_1.kts:1:14)
org.camunda.bpm.engine.ScriptCompilationException: Unable to compile script: Error: ERROR Unresolved reference: task (ScriptingHostd60d80d_Line_1.kts:1:14)
	at org.camunda.bpm.engine.impl.scripting.SourceExecutableScript.compile(SourceExecutableScript.java:112) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.scripting.SourceExecutableScript.compileScript(SourceExecutableScript.java:84) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.scripting.SourceExecutableScript.evaluate(SourceExecutableScript.java:57) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.scripting.ExecutableScript.execute(ExecutableScript.java:63) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.scripting.env.ScriptingEnvironment.execute(ScriptingEnvironment.java:101) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.scripting.env.ScriptingEnvironment.execute(ScriptingEnvironment.java:87) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.delegate.ScriptInvocation.invoke(ScriptInvocation.java:47) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.delegate.DelegateInvocation.proceed(DelegateInvocation.java:58) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.delegate.DefaultDelegateInterceptor.handleInvocationInContext(DefaultDelegateInterceptor.java:92) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.delegate.DefaultDelegateInterceptor.handleInvocation(DefaultDelegateInterceptor.java:63) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.bpmn.behavior.ScriptTaskActivityBehavior$1.call(ScriptTaskActivityBehavior.java:55) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.bpmn.behavior.ScriptTaskActivityBehavior$1.call(ScriptTaskActivityBehavior.java:51) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior.executeWithErrorPropagation(AbstractBpmnActivityBehavior.java:90) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.bpmn.behavior.ScriptTaskActivityBehavior.performExecution(ScriptTaskActivityBehavior.java:51) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.bpmn.behavior.TaskActivityBehavior.execute(TaskActivityBehavior.java:69) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationActivityExecute$2.callback(PvmAtomicOperationActivityExecute.java:61) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationActivityExecute$2.callback(PvmAtomicOperationActivityExecute.java:50) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.continueIfExecutionDoesNotAffectNextOperation(PvmExecutionImpl.java:2039) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationActivityExecute.execute(PvmAtomicOperationActivityExecute.java:42) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationActivityExecute.execute(PvmAtomicOperationActivityExecute.java:31) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.AtomicOperationInvocation.execute(AtomicOperationInvocation.java:99) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.invokeNext(CommandInvocationContext.java:131) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performNext(CommandInvocationContext.java:111) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:86) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:634) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:608) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl$6.callback(PvmExecutionImpl.java:1978) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl$6.callback(PvmExecutionImpl.java:1975) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.continueExecutionIfNotCanceled(PvmExecutionImpl.java:2045) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.dispatchDelayedEventsAndPerformOperation(PvmExecutionImpl.java:1994) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.dispatchDelayedEventsAndPerformOperation(PvmExecutionImpl.java:1975) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationTransitionNotifyListenerStart.eventNotificationsCompleted(PvmAtomicOperationTransitionNotifyListenerStart.java:60) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationTransitionNotifyListenerStart.eventNotificationsCompleted(PvmAtomicOperationTransitionNotifyListenerStart.java:30) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.core.operation.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:66) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.AtomicOperationInvocation.execute(AtomicOperationInvocation.java:99) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.invokeNext(CommandInvocationContext.java:131) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performNext(CommandInvocationContext.java:111) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:86) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:76) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:643) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:618) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.core.operation.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:62) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.AtomicOperationInvocation.execute(AtomicOperationInvocation.java:99) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.invokeNext(CommandInvocationContext.java:131) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performNext(CommandInvocationContext.java:111) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:86) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:76) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:643) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:618) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.core.operation.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:62) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.AtomicOperationInvocation.execute(AtomicOperationInvocation.java:99) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.invokeNext(CommandInvocationContext.java:131) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performNext(CommandInvocationContext.java:111) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:86) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:76) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:643) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:618) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.core.operation.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:62) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.AtomicOperationInvocation.execute(AtomicOperationInvocation.java:99) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.invokeNext(CommandInvocationContext.java:131) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performNext(CommandInvocationContext.java:111) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:86) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:634) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:608) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationTransitionCreateScope.scopeCreated(PvmAtomicOperationTransitionCreateScope.java:38) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationCreateScope.execute(PvmAtomicOperationCreateScope.java:54) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationCreateScope.execute(PvmAtomicOperationCreateScope.java:28) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.AtomicOperationInvocation.execute(AtomicOperationInvocation.java:99) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.invokeNext(CommandInvocationContext.java:131) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performNext(CommandInvocationContext.java:118) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext$1.call(CommandInvocationContext.java:102) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext$1.call(CommandInvocationContext.java:100) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.context.ProcessApplicationClassloaderInterceptor.call(ProcessApplicationClassloaderInterceptor.java:48) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.application.AbstractProcessApplication.execute(AbstractProcessApplication.java:121) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.application.AbstractProcessApplication.execute(AbstractProcessApplication.java:132) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.context.Context.executeWithinProcessApplication(Context.java:206) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performNext(CommandInvocationContext.java:100) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:86) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:76) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.jobexecutor.AsyncContinuationJobHandler.execute(AsyncContinuationJobHandler.java:81) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.jobexecutor.AsyncContinuationJobHandler.execute(AsyncContinuationJobHandler.java:40) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.persistence.entity.JobEntity.execute(JobEntity.java:134) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.cmd.ExecuteJobsCmd.execute(ExecuteJobsCmd.java:110) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.cmd.ExecuteJobsCmd.execute(ExecuteJobsCmd.java:43) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandExecutorImpl.execute(CommandExecutorImpl.java:28) ~[camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:110) [camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:72) [camunda-engine-spring-7.15.0.jar:7.15.0]
	at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) [spring-tx-5.3.4.jar:5.3.4]
	at org.camunda.bpm.engine.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:70) [camunda-engine-spring-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.ProcessApplicationContextInterceptor.execute(ProcessApplicationContextInterceptor.java:70) [camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.CommandCounterInterceptor.execute(CommandCounterInterceptor.java:35) [camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:33) [camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.jobexecutor.ExecuteJobHelper.executeJob(ExecuteJobHelper.java:57) [camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.jobexecutor.ExecuteJobsRunnable.executeJob(ExecuteJobsRunnable.java:110) [camunda-engine-7.15.0.jar:7.15.0]
	at org.camunda.bpm.engine.impl.jobexecutor.ExecuteJobsRunnable.run(ExecuteJobsRunnable.java:71) [camunda-engine-7.15.0.jar:7.15.0]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
	at java.lang.Thread.run(Thread.java:834) [?:?]
Caused by: javax.script.ScriptException: Error: ERROR Unresolved reference: task (ScriptingHostd60d80d_Line_1.kts:1:14)
	at org.jetbrains.kotlin.cli.common.repl.KotlinJsr223JvmScriptEngineBase.compile(KotlinJsr223JvmScriptEngineBase.kt:74) ~[kotlin-compiler-embeddable-1.5.10.jar:1.5.10-release-890 (1.5.10)]
	at org.jetbrains.kotlin.cli.common.repl.KotlinJsr223JvmScriptEngineBase.compile(KotlinJsr223JvmScriptEngineBase.kt:35) ~[kotlin-compiler-embeddable-1.5.10.jar:1.5.10-release-890 (1.5.10)]
	at org.camunda.bpm.engine.impl.scripting.SourceExecutableScript.compile(SourceExecutableScript.java:105) ~[camunda-engine-7.15.0.jar:7.15.0]
	... 97 more

Looks like kotlin script compiles without variables context.

Can you please explain such behavior

UPD
Found some interesting difference between groovy and kotlin
For example we have script

println("######## Hello groovy scipt task!")
println(ololo) //variable "ololo" is undefined and does not exist at all

So, when we are using groovy script engine, it compiles well. Method org.camunda.bpm.engine.impl.scripting.SourceExecutableScript#compileScript executes successfully.
But when this script evaluates, method org.camunda.bpm.engine.impl.scripting.SourceExecutableScript#evaluateScript fails as expected because No such property: ololo for class: Script2

When kotlin scipt engine is used, it fails while executing method org.camunda.bpm.engine.impl.scripting.SourceExecutableScript#compileScript

Looks like kotlin script engine is more strict and does not allow undefined variables at compile time

UPD2
I found issue https://youtrack.jetbrains.com/issue/KT-15125 that current implementation of JSR223 by kotlin does not support direct variable binding

Current implementation allow access to the bindings via
bindings: Map<String, Any?> variable
Proper implementation should map all names from this map into script variables directly, and also put other declared variables into bindings map back.

This bug is in fixed state, but maybe it does not work in proper way

So, you can access variables via bindings: Map<String, Any?> - it works. bindings::class.simpleName is reference to org.camunda.bpm.engine.impl.scripting.engine.ScriptBindings