Search code examples
scalaplayframeworknashornplayframework-2.5

Implementing Nashorn in Play for Scala controller


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)
    }


 }

Solution

  • 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.