Kotlin JSR-223 ScriptEngineFactory in fat jar - Can't find the kotlin compiler compiler
I have a fat jar where I am trying to get a Kotlin instance ScriptEngine
.
For debugging purposes, I iterate through the available Script Engine Factories and get the engines.
val scriptEngineManager = ScriptEngineManager() for (factory in scriptEngineManager.engineFactories) { val scriptEngine = factory.scriptEngine }
When it hits the Kotlin engine, it crashes with the following exception:
Exception in thread "main" java.io.FileNotFoundException: Cannot find kotlin compiler jar, set kotlin.compiler.jar property to proper location
at org.jetbrains.kotlin.script.jsr223.KotlinJsr223ScriptEngineFactoryExamplesKt$kotlinCompilerJar$2.invoke(KotlinJsr223ScriptEngineFactoryExamples.kt:100)
at org.jetbrains.kotlin.script.jsr223.KotlinJsr223ScriptEngineFactoryExamplesKt$kotlinCompilerJar$2.invoke(KotlinJsr223ScriptEngineFactoryExamples.kt)
at kotlin.SynchronizedLazyImpl.getValue(Lazy.kt:130)
at org.jetbrains.kotlin.script.jsr223.KotlinJsr223ScriptEngineFactoryExamplesKt.getKotlinCompilerJar(KotlinJsr223ScriptEngineFactoryExamples.kt)
at org.jetbrains.kotlin.script.jsr223.KotlinJsr223ScriptEngineFactoryExamplesKt.access$getKotlinCompilerJar$p(KotlinJsr223ScriptEngineFactoryExamples.kt:1)
at org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmDaemonLocalEvalScriptEngineFactory.getScriptEngine(KotlinJsr223ScriptEngineFactoryExamples.kt:56)
at davidsiro.invoices.InvoiceGeneratorKt.generateInvoice(invoiceGenerator.kt:16)
at davidsiro.invoices.MainKt.main(main.kt:11)
My fat jar contains all the dependencies (albeit unpacked), including the Kotlin compiler. I am using Maven Assembly Plugin to build it, which is configured like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>${main.class}</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
Any ideas?
Update
For the record, I tried with both KotlinJsr223JvmLocalScriptEngineFactory and KotlinJsr223JvmDaemonLocalEvalScriptEngineFactory with the same result.
source to share
The JSR223 factories in kotlin-script-util try to find a compiler to set up compilation. In your case, you need to write your own factory to explicitly specify the classpath of the compilation script, eg.
class MyScriptEngineFactory : KotlinJsr223JvmScriptEngineFactoryBase() { override fun getScriptEngine(): ScriptEngine = KotlinJsr223JvmLocalScriptEngine( Disposer.newDisposable(), this, classpath, // !!! supply the script classpath here KotlinStandardJsr223ScriptTemplate::class.qualifiedName!!, { ctx, types -> ScriptArgsWithTypes(arrayOf(ctx.getBindings(ScriptContext.ENGINE_SCOPE)), types ?: emptyArray()) }, arrayOf(Bindings::class) ) }
You need to put the following cans in classpath
:
-
kotlin-script-util.jar
- it contains a template class used as a superclass for the script -
kotlin-script-runtime.jar
- for base classes used in scripts - any other jars you need to use in your scenarios is likely -
kotlin-stdlib.jar
You can put your fat jar instead, but that will mean whatever is available from it will be available from your scripts. Not to mention the compiler overhead.
source to share