Creating Groovy Object

Currently in BPMN Flows, we send in REST Requests with JSON strings, for example here is an example of a variable:
“applicationDetails”:{
“type”:“Json”,
“value”:“{"sourceUser":"m12345", "applicationName":"GCAS", "aplicationId":"16627"}” }

When received in a BPMN flow, we immediately convert it to a object using Javascript:

var reqJson= execution.getVariable(‘applicationDetails’);
var applicationDetailsObj = JSON.parse(reqJson);
execution.setVariable(“applicationDetailsObj”, applicationDetailsObj);

We can then use and modify this object throughout the flow in Javascript.

*** PROBLEM: Because Javascript does not play nicely with Kubernetes/JVM environments we need to convert our Javascript to Groovy (trust me when I say this is necessary).

My Question is, how to I do the above code in Groovy? The key problem is the “escape” character () being used for the double-quotes. I have tried JsonSlurper but it will not work directly on a JSON String with the escaped characters like JSON.parse() did.
I have tried:

def appDetails = execution.getVariable(“applicationDetails”)
def jsonSlurper = new JsonSlurper()
def appDetailsObj = jsonSlurper.parseText(appDetails)

but get the following error: Cannot instantiate process definition 621d8808-82c9-11e8-b104-d481d75f0924: Unable to evaluate script: groovy.lang.MissingMethodException: No signature of method: groovy.json.JsonSlurper.parseText() is applicable for argument types: (org.camunda.spin.impl.json.jackson.JacksonJsonNode) values: [{"sourceUser":"m12345","applicationName":"GCAS","aplicationId":"16627"}]\nPossible solutions: parseText(java.lang.String), parse([B), parse([C), parse(java.io.File), parse(java.io.InputStream), parse(java.io.Reader)

def appDetailsObj = jsonSlurper.parseText(appDetails.toString())

You are trying to parse a SPIN object using a String parser. You need to tell spin to covert to a string first.

You can also use the following nashorn JavaScript which will return your object as a java map:

Java.asJSONCompatible(
   {
      'task_response': taskResponse,
      'reviewer': "john"
    }
)

You can also look at the following: https://docs.camunda.org/javadoc/camunda-bpm-platform/7.9/org/camunda/bpm/engine/impl/util/json/JSONObject.html

Which will let you parse a Json string into a java type JSONObject

1 Like

Thanks. The addition of .toString() worked.

We are trying to avoid any nashorn JavaScript by switching to Groovy. We discovered that Nashorn Javascript does not play nicely with JVMs in a Kubernetes environment. We were experiencing terrible Garbage Collection and POD stability issues when trying to run higher volumes. We consulted with Camunda, and they did not have a fix for the Nashorn Javascript problems, so we switched to Groovy. Our testing indicates it does not have the same problems on a JVM.

@sseymour can you share some details about your setup and the performance wall you were hitting?

I cannot attach our complete analysis, but here is the response from Camunda:

Given the characteristics of Nashorn’s usage within Camunda, we would expect it to run more slowly than both “native” Java code and - potentially - other scripting engines as well. This is because the scripting engine isn’t cached and because scripts aren’t compiled and reused. The former - the fact that it isn’t cached - is due to the fact that Nashorn can’t be shared between multiple threads (a characteristic of the scripting engine itself), and the latter is due to incompatibilities with some of the functionality that we need to provide in our scripts.
Our recommendation to you is first to utilize “native” Java code in situations where performance is important. If you must use scripts, please use Groovy; as you’ve noted yourself, it runs faster than does JavaScript within Camunda.
If you’re looking to support another (more modern?) language that can be used within Camunda process applications, you may want to consider Kotlin. While Kotlin can be used as a JSR-223 scripting language, which wouldn’t be supported by Camunda, you can also write Kotlin and compile it down to Java class files, which would obviously work in Camunda just like class files compiled from Java source.

Below are some additional links to other comments:

The performance impact of scripting in processes
Major Performance Issues with Java 8 ScriptEngine Compared to Java 7

2 Likes

@sseymour can you also take a look at GraalVm where a upcoming RC release will decouple the GraalJS component into a standalone jar, thus allowing it to be used in the standard JDK. GraalJS is much faster than nashorn and is ~full es6

I believe it was talked about for RC4 (next rc release)

I have java object in persisted variable and trying to access back in script task using groovy but getting below exception

Caused by: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Script4.groovy: 2: unable to resolve class JsonSlurper
@ line 2, column 14.
def parser = new JsonSlurper()

Code in Script task:

def entity = execution.getVariable('persisted')
def parser = new JsonSlurper()
def fileDetails = parser.parseText(entity.toString())

TIA
yadav

import groovy.json.JsonSlurper