views:

250

answers:

1

Hi,

I want to create a class at run-time in Scala. For now, just consider a simple case where I want to make the equivalent of a java bean with some attributes, I only know these attributes at run time.

How can I create the scala class? I am willing to create from scala source file if there is a way to compile it and load it at run time, I may want to as I sometimes have some complex function I want to add to the class. How can I do it?

I worry that the scala interpreter which I read about is sandboxing the interpreted code that it loads so that it won't be available to the general application hosting the interpreter? If this is the case, then I wouldn't be able to use the dynamically loaded scala class.

Anyway, the question is, how can I dynamically create a scala class at run time and use it in my application, best case is to load it from a scala source file at run time, something like interpreterSource("file.scala") and its loaded into my current runtime, second best case is some creation by calling methods ie. createClass(...) to create it at runtime.

Thanks, Phil

+2  A: 

There's not enough information to know the best answer, but do remember that you're running on the JVM, so any techniques or bytecode engineering libraries valid for Java should also be valid here.

There are hundreds of techniques you might use, but the best choice depends totally on your exact use case, as many aren't general purpose. Here's a couple of ideas though:

  • For a simple bean, you may as well just use a map, or look into the DynaBean class from apache commons.

  • For more advanced behaviour you could invoke the compiler explicitly and then grab the resulting .class file via a classloader (this is largely how JSPs do it)

  • A parser and custom DSL fit well in some cases. As does bean shell scripting.

Check out the ScalaDays video here: http://days2010.scala-lang.org/node/138/146 which demonstrates the use of Scala as a JSR-223 compliant scripting language. This should cover most scenarios where you'd want to evaluate Scala at runtime.

You'll also want to look at the email thread here: http://scala-programming-language.1934581.n4.nabble.com/Compiler-API-td1992165.html#a1992165

This contains the following sample code:

// We currently call the compiler directly 
// To reduce coupling, we could instead use ant and the scalac ant task 

import scala.tools.nsc.{Global, Settings} 
import scala.tools.nsc.reporters.ConsoleReporter
{ 
  // called in the event of a compilation error 
  def error(message: String): Nothing = ... 

  val settings = new Settings(error) 
  settings.outdir.value = classesDir.getPath 
  settings.deprecation.value = true // enable detailed deprecation warnings 
  settings.unchecked.value = true // enable detailed unchecked warnings 

  val reporter = new ConsoleReporter(settings) 

  val compiler = new Global(settings, reporter) 
  (new compiler.Run).compile(filenames) 

  reporter.printSummary 
  if (reporter.hasErrors || reporter.WARNING.count > 0) 
  { 
             ... 
  } 
} 


val mainMethod: Method = { 
  val urls = Array[URL]( classesDir.toURL ) 

  val loader = new URLClassLoader(urls) 

  try { 
    val clazz: Class = loader.loadClass(...) 

    val method: Method = clazz.getMethod("main", Array[Class]( classOf[Array[String]] )) 
    if (Modifier.isStatic(method.getModifiers)) { 
       method 
    } else { 
      ... 
    } 
  } catch { 
    case cnf: ClassNotFoundException => ... 
    case nsm: NoSuchMethodException => ... 
  } 
} 

mainMethod.invoke(null, Array[Object]( args )) 
Kevin Wright
I want to create it from scala source code, lets say I have the scala source code as a string, how can I do it?
Phil
In addition to the above. The following link may also help (I don't claim to be an expert in the area):http://scala-programming-language.1934581.n4.nabble.com/Compiling-a-Scala-Snippet-at-run-time-td2000704.html
I have troubles using this code, in particular I can't get why you put a code block right after the import. Is the code complete or there are some lines missing?
mariosangiorgio