Eval in Kotlin

I tried to port this simple example using Java/Groovy to Kotlin/Kotlin, but I can not get it working.

Code:

import groovy.util.Eval;

public class MetaEval
{
  public static void main (String... args)
  {
    System.out.println (Eval.me ("2+3"));
  }
}

Compile:

$ /usr/lib/jvm/java-8-openjdk-amd64/bin/javac -cp .:/usr/share/java/groovy-all.jar MetaEval.java

Run:

$ /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java -cp .:/usr/share/java/groovy-all.jar MetaEval 
5

I already asked on SO without luck.

Kotlin example:

import javax.script.*

fun main () {
  val engine = ScriptEngineManager().getEngineByExtension("kts")!!
  println (engine.eval("2 + 3"))
}

How do I have to compile and run it on the command line without the use of any fancy build tools or IDEs? Which JARs are required to run it directly with Java? I tried all, but it does not seem to be enough:

java -cp .:$(echo ../kotlinc/lib/*.jar | tr ' ' ':'):livetribe-jsr223.jar HelloKt 
ScriptEngineManager providers.next(): javax.script.ScriptEngineFactory: Provider org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory not found
Exception in thread "main" java.lang.NullPointerException
        at HelloKt.main(hello.kt:4)
        at HelloKt.main(hello.kt)
1 Like

The error is self-explanatory. You did not load a JSR223 provider for kotlin. It does not come out of the box for kotlin like it does for groovy. You need to at least add the engine to the build (not only this artifact but all its dependencies as well).

By the way, you can keep using groovy as a scripting language, it works perfectly fine inside kotlin and the size of groovy jar is much smaller, then the size of kotlin compiler.

1 Like

You need to some small adjustmnets in order to make Kotlin Scripting work with the ScriptEngine.

Personally I’ve wrapped the eval with this code (it’s Kotlin, but I believe you can adapt it to Java):

In the build file I had to add the following:

 // kotlin scripting
    compile "org.jetbrains.kotlin:kotlin-script-runtime"
    compile "org.jetbrains.kotlin:kotlin-compiler-embeddable"
    compile "org.jetbrains.kotlin:kotlin-script-util"
    compile "org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable"

And in the folder src/main/resources/META-INF/services/ I create a file called javax.script.ScriptEngineFactory with the following content: org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngineFactory.

Look here in the services folder.

It’s a little bit cumberstone to run Kotlin Scripts from Java (or Kotlin), but not impossible.

1 Like

It is a bit convoluted I agree.

There is a way to do it in yet another way, have a look at my comment and code in: Running Kotlin Scripts with bindings from a Kotlin program using ScriptEngine

As far as I understand, https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-scripting-jsr223/1.4.10 does most of the configuration. It includes all needed dependencies transitively and has a service provider configured.

JSR223 is not a preferred way to call kotlin scripts in kotlin, but still, it should work without a lot of fuss.

1 Like

Agreed, it works and is decently easy to set up (despite lacking documentation). I couldn’t get it to work with shadow fatjars so I switched to the non jsr223 way.