The code below executes a Nashorn/Javascript script in a Play (2.5) for Scala controller. I inject a class to get the engine that runs the script.
I researched online and there are mixed opinions with regard to Nashorn's thread safety, so I'm unclear. Is the getEngine
method below, called from a Play controller, thread safe?
@Singleton
class JavascriptEngine {
val factory = new NashornScriptEngineFactory
def getEngine = { // <-- thread safe?
factory.getScriptEngine()
}
}
class Test @Inject()(je: JavascriptEngine) extends Controller {
def test = Action { request =>
val script = "var x = 'this is script 1'; "
runJS(script)
Ok("some response")
}
def runJS (script: String) = {
val engine = je.getEngine
engine.eval(script)
val x = engine.get("x")
println(x)
}
}
From the javadoc of getScriptEngine
:
A new ScriptEngine is generally returned, but implementations may pool, share or reuse engines.
So, without looking at the implementation, in the general case (if a new engine gets created always), this is thread-safe.
In the other case, if the engines get pooled or shared, I would assume the factory code internally handles pooling / sharing in a thread-safe manner.
Looking at https://alvinalexander.com/java/jwarehouse/openjdk-8/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java.shtml it seems the factory indeed always returns a newly created engine.