karate: karate.callSingle/callonce crashes where karate.call succeeds

Hi, In our karate-config, I use a lot of Java.type(‘XXX’) to call custom Java code. As it is somehow “heavy” (authentication against a provider), I want this to get called only once for all my tests, and not before each of my 400+ tests (thus the callSingle in karate-config, instead of having all the code in karate-config).

In karate 0.9.6, the following worked :

karate-config.js :

function configure_karate() {
    var load_config=karate.callSingle('classpath:load-config.js')
    return load_config
}

load-config.js :

function load_config() {
    var config = {}
    config.spec = Java.type('package.CustomJavaClass').spec // spec if a static function of CustomJavaClass
    return config
}

while it crashes using the latest Karate releases (tried with both 1.0.1 and 1.1.0.RC2) with following stacktrace :

org.graalvm.polyglot.PolyglotException
- com.intuit.karate.graal.JsFunction.<init>(JsFunction.java:39)
- com.intuit.karate.core.ScenarioEngine.recurseAndDetachAndDeepClone(ScenarioEngine.java:1208)
- com.intuit.karate.core.ScenarioEngine.lambda$recurseAndDetachAndDeepClone$15(ScenarioEngine.java:1225)
- java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:723)
- com.intuit.karate.core.ScenarioEngine.recurseAndDetachAndDeepClone(ScenarioEngine.java:1225)
- com.intuit.karate.core.ScenarioEngine.recurseAndDetachAndDeepClone(ScenarioEngine.java:1201)
- com.intuit.karate.core.ScenarioBridge.callSingle(ScenarioBridge.java:235)

I know there have been huge changes from 0.9.6 to 1+, but what bugs me is that using karate.call('classpath:load-config.js') works in karate 1+ versions.

So, the behavior is different between karate.call and karate.callSingle.

After some digging into karate inner sources, starting from ScenarioBridge, and some testing, the problem is due to the fact spec is a function, and karate.call and karate.callSingle handle functions differently.

To my understanding, those functions should have the same behavior, with the latter caching the result for subsequent calls. Am I wrong ? I set up a minimal project in this repo for easier reproduction. https://github.com/zgael/karateconfig

Feel free to ask for clarifications if needed !

Thanks!

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 15 (13 by maintainers)

Commits related to this issue

Most upvoted comments

attention all cc @zgael @joelpramos @aleruz

I figured out a way where you can use Java functions safely even within a callonce or karate.callSingle(), it is not completely straightforward, but I think a very reasonable compromise. it makes me relieved because I am confident Karate can be made to work for advanced JMS and Kafka kinds of use-cases in a stable way, where earlier I thought graal would very badly get in the way

see doc screenshot below, and direct link is here: https://github.com/intuit/karate/tree/develop#java-function-references

image

sure. one of the points above is that you shouldn’t put Java methods and such in a callSingle() do it as many times as you want in a normal call. callSingle() is designed for caching data, not java code.

for readability, you can wrap it into a feature following the instructions here: https://github.com/intuit/karate#multiple-functions-in-one-file

no not too late, as of now I consider we are done with the fixes here. FWIW here is what we have in the documentation in the next version - screenshot below: https://github.com/intuit/karate/tree/develop#karatecallsingle

image