Hi, I’m trying to use Kotlin (v1.2.60) packaged in a .war file deployed to WildFly (v13.0.0.Final), to be accessed through the javax.script API (JSR 223). WEB-INF/lib contains the jars from mvn packages “org.jetbrains.kotlin:kotlin-compiler-embeddable:1.2.60” and “org.jetbrains.kotlin:kotlin-script-util:1.2.60”.
Trying a simple eval like this:
ScriptEngine e = new KotlinJsr223JvmLocalScriptEngineFactory().getScriptEngine();
e.eval("1+1");
Gives this stacktrace:
java.lang.IllegalStateException: Resource not found: /kotlin/jvm/JvmStatic.class
at deployment.kotlin_script_test.war//org.jetbrains.kotlin.script.util.impl.PathUtilKt.getResourcePathForClass(pathUtil.kt:76)
at deployment.kotlin_script_test.war//org.jetbrains.kotlin.script.util.KotlinJars.getLib(context.kt:147)
at deployment.kotlin_script_test.war//org.jetbrains.kotlin.script.util.KotlinJars$stdlibOrNull$2.invoke(context.kt:151)
at deployment.kotlin_script_test.war//org.jetbrains.kotlin.script.util.KotlinJars$stdlibOrNull$2.invoke(context.kt:119)
at deployment.kotlin_script_test.war//kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at deployment.kotlin_script_test.war//org.jetbrains.kotlin.script.util.KotlinJars.getStdlibOrNull(context.kt)
at deployment.kotlin_script_test.war//org.jetbrains.kotlin.script.util.KotlinJars.getKotlinScriptStandardJars(context.kt:168)
at deployment.kotlin_script_test.war//org.jetbrains.kotlin.script.util.ContextKt.scriptCompilationClasspathFromContextOrStlib(context.kt:109)
at deployment.kotlin_script_test.war//org.jetbrains.kotlin.script.util.ContextKt.scriptCompilationClasspathFromContextOrStlib$default(context.kt:106)
at deployment.kotlin_script_test.war//org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmDaemonLocalEvalScriptEngineFactory.getScriptEngine(KotlinJsr223ScriptEngineFactoryExamples.kt:46)
at deployment.kotlin_script_test.war//kotlin.KotlinEvaluator.eval(KotlinEvaluator.java:10)
Running the code in a standalone app outside a web container with the same dependencies works fine.
Any ideas? What am I missing? Is the Kotlin script engine ready to be run inside a webapp?
I’ve tried to debug this and found that the method extractRoot from libraries/tools/kotlin-script-util/src/main/kotlin/org/jetbrains/kotlin/script/util/impl/pathUtil.kt is called with an URL like this:
where “vfs” seems to be a special WildFly Virtual File System protocol which the extractRoot method cannot handle because it’s hard-wired to “jar” and “file”.
Seems this is an untested path. We’ll do something about it, but meanwhile, you can workaround it by specifying script compilation classpath explicitly via kotlin.compiler.classpath property. You’ll need to put at least kotlin-script-util there, and for any useful script, quite likely kotlin-stdlib as well.
Hi, I am getting exactly the same errors in v1.3.10 trying to do the same in OSGi runtime (equinox). Script Engine can be created with the compiler classpath workaround, but the errors come when I try to execute a script.
The kotlin script support is implemented by compiling the code at runtime and then executing the resulting code. It means you need access to the Kotlin compiler at runtime. It also means that this is not the fastest thing in the world.
IMO, this is exactly what the javax.script mechanism is for. There are situations where you cannot (or prefer not to) package everything at compile-time but deploy certain parts of your code or configuration-as-code at runtime. Using Kotlin, you’d of course have a small performance penalty when that code is run for the first time, but after that it will run and interoperate the same as pre-compiled code.
The original issue is that kotlin is not yet able to compile with classes directly from current classloader (as many interpreted languages like groovy and clojure can), so it needs to get a classpath in a form that the compiler will be able to use. And in a webapp environment this is not trivial.
There is an issue about this - https://youtrack.jetbrains.com/issue/KT-27956 - we’re going to address it in some not too distant future. And then these problems should go away.