2
votes

I have to use scala parser inside Play Framework application.

import scala.tools.nsc._

trait Foo
class Parser {
    def parse(code: String) = {
        val settings = new Settings
        settings.embeddedDefaults[Foo]
        val interpreter = new Interpreter(settings)
        interpreter.parse(code)
    }
}

I have following dependency in Build.scala

"org.scala-lang" % "scala-compiler" % "2.9.1"

This code works when build using SBT. In Play it ends with NullPointerException and:

Failed to initialize compiler: object scala not found.

** Note that as of 2.8 scala does not assume use of the java classpath.

** For the old behavior pass -usejavacp to scala, or if using a Settings

** object programatically, settings.usejavacp.value = true.

Build.scala

import sbt._
import Keys._
import PlayProject._

object ApplicationBuild extends Build {

    val appName         = "com.qwerty.utils"
    val appVersion      = "1.0-SNAPSHOT"
    val scalaVersion    = "2.9.1"

    val appDependencies = Seq(
        "org.scala-lang" % "scala-compiler" % "2.9.1"
    )
    
    val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings(
      // Add your own project settings here
    
    )

}
1
Did you mark it as a library dependency or build-level dependency? Anyway you may want to add your Build.scala file to the question. - Tomer Gabel
On which line do you get the NPE? - opyate
Also, how are you running your app? - opyate
I got error in interpreter.parse(code) - Mateusz

1 Answers

1
votes

For background on embeddedDefaults, see the original proposal.

The container (Play) must define the 'app.class.path' and 'boot.class.path' resources and then embeddedDefaults will use them to configure the interpreter properly for the environment. So, this is an enhancement for Play.

If you can pass the necessary classpaths into your application, you can configure classpaths and classloaders explicitly yourself with something like:

val settings = new Settings
settings.classpath.value = "<classpath>"
settings.bootclasspath.value =
  settings.bootclasspath.value + File.pathSeparator +
  "<extra-bootclasspath>"
val interpreter = new Interpreter(settings) {
    override def parentClassLoader = classOf[Foo].getClassLoader
}
interpreter.parse(code)

The bootclasspath should generally contain scala-library.jar and the classpath should contain the application jars.