1

Scala JSR223 script support since 2.11

e.eval("""s"a is $a, s is $s"""")

I added Scala 2.13 jars and tried to execute script, it can display constants in response

But I can't add JMeter's bind variables as log, I tried with:

log.info(a);
$log.info(a);

Or can't print values to log, tried also

var a:Int =  10
println(a)

JMeter's bindings code:

 Bindings bindings = engine.createBindings();
 final Logger logger = LoggerFactory.getLogger(JSR223_INIT_FILE);
 bindings.put("log", logger); // $NON-NLS-1$ (this name is fixed)       
 engine.eval(reader, bindings);

Tried also using bindings but it isn't in context

bindings.get("log").info("aa");

Exception

ERROR o.a.j.p.j.s.JSR223Sampler: Problem in JSR223 script JSR223 Sampler, message: javax.script.ScriptException: not found: value bindings

How can I submit Scala JSR223 script using JMeter/Java bindings variables?

EDIT

Open Scala issue JSR223 - Engine ignores bindings parameters

3
  • Odd. When trying this out myself, I see that there are no registered ScriptEngineFactory instances at all. Commented Aug 14, 2019 at 17:52
  • @MarkKegel did you add latest jars to classpath? Commented Aug 14, 2019 at 17:55
  • D'oh. That was the issue. Commented Aug 14, 2019 at 18:02

1 Answer 1

1
+50

The core of the issue is that injected bindings are seen by the Scala script engine as having a type of Any. To use the injected bindings you either have to cast them to the appropriate type on every use, or you need to inject them as a 'shadow binding' and then re-bind in-engine using the appropriate type.

Here is my Main.scala, where I demonstrate the latter approach:

import javax.script.ScriptEngineManager

import org.slf4j.Logger
import org.slf4j.LoggerFactory

object Main extends App {

  val logger: Logger = LoggerFactory.getLogger("main")

  val e = new ScriptEngineManager().getEngineByName("scala")
  e.put("a", 1)
  e.put("s", "String")

  // Since the variable will have a type of Object, inject under a different name, and then bind to the
  // "correct" name using eval.
  e.put("logInjected", logger)

  println(e.eval(""" s"a is $a, s is $s" """))
  println(e.eval(""" logInjected.toString """))

  e.eval(""" val log = logInjected.asInstanceOf[org.slf4j.Logger] """)
  e.eval(""" log.info("hello from injected logger") """)

  e.eval(
    """ // Or can you do this
      | import org.slf4j.Logger
      | import org.slf4j.LoggerFactory
      |
      | val l = LoggerFactory.getLogger("script")
      |
      | l.error("hello from script")
      |
      |""".stripMargin)
}

And my build.sbt I used to:

name := "s213"

version := "1.0"

scalaVersion in ThisBuild := "2.13.0"

libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value
libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.3.0-alpha4"
libraryDependencies += "org.slf4j" % "slf4j-api" % "2.0.0-alpha0"

The output from running Main will be:

a is 1, s is String
Logger[main]
[main] INFO  main - hello from injected logger 
[main] ERROR script - hello from script 
Sign up to request clarification or add additional context in comments.

1 Comment

So variables added to bindings are ignored/can't be used in scala when using engine.eval(reader, bindings)? Isn't it a bug?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.