Examples on how to setup a maven war project using Kotlin to generate client side Javascript

Hi everyone!

I’ve seen Kotlin demonstrated on JavaZone (Oslo, Norway) once and it looked quite promising.
I’ve been using Typescript as the language for writing client side Javascript (the administration console of the product) in another Java project, but now I’m on another project and are hoping to use Kotlin instead.

But I’m struggling to setup a Java project using maven, which builds a war including:

  • REST resources/Servlet  (plain Java, no Kotlin involved)
  • index.html (which uses generated javascript from Kotlin compilation)
  • JavaScript generated from Kotlin

Could JetBrains please provide more examples using Kotlin to generate client side Javascript on a Java EE project?

That would be much appricated.

Thanks,
Jørund

Hi Jørund,

Do you have a single module in your project or you have multiple modules? Here’s an example of targeting JS with Maven

https://github.com/cy6erGn0m/html4k

We have the docs for Gradle updated to target JS

http://kotlinlang.org/docs/reference/using-gradle.html

but not yet Maven. Will log it and we’ll work on it.

https://youtrack.jetbrains.com/issue/KT-7611

Have you successfully managed to call your back-end code using Kotlin to JavaScript?

Hi Hadi and thanks for the reply!

I’ve not yet successfully managed to build any war including kotlin-generated code.

I’m still working on getting the generated Javascript files from Kotlin to be assembed into the war.

One thing you probably can tell me is - which kotlin files are needed to be included in the HTML? I get two JS-files generated (ends up in target/classes) from my Kotlin Javascript module:

  • One containing my simple class named “DetectionStep”:
    (function (Kotlin) {
      ‘use strict’;
      var _ = Kotlin.defineRootPackage(null, /** @lends _ */ {
      DetectionStep: Kotlin.createClass(null, function (path) {
      this.path = path;
      })
      });
      Kotlin.defineModule(‘imlink-babel-admin-js’, _);
    }(Kotlin));
  • And another called meta beginning with: // Kotlin.kotlin_module_metadata(1, “imlink-babel-admin-js”, “H4sIAAAAAAAAALVa2XMcRxnflqWV5tPqPm…

This is the Maven POM that generates this:
 
<?xml version=“1.0” encoding=“UTF-8”?>
<project xmlns=”http://maven.apache.org/POM/4.0.0"
  xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance
  xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd>
  <modelVersion>4.0.0</modelVersion>
  <parent>
  <groupId>no.logiq.babel.admin</groupId>
  <artifactId>imlink-babel-admin</artifactId>
  <version>1.0-SNAPSHOT</version>
  </parent>
  <artifactId>imlink-babel-admin-js</artifactId>
  <version>1.0-SNAPSHOT</version>
  <dependencies>
  <dependency>
           <groupId>org.jetbrains.kotlin</groupId>
           <artifactId>kotlin-js-library</artifactId>
           <version>${kotlin.version}</version>
  </dependency>

  </dependencies>

  <build>
  <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
  <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
  <plugins>
           <plugin>
           <artifactId>kotlin-maven-plugin</artifactId>
           <groupId>org.jetbrains.kotlin</groupId>
           <version>${kotlin.version}</version>
           <executions>
                   <execution>
                   <id>compile</id>
                   <phase>compile</phase>
                   <goals>
                           <goal>js</goal>
                   </goals>
                   <configuration>
                           <outputFile>${project.build.outputDirectory}/${project.artifactId}.js</outputFile>
                           <metaFile>${project.build.outputDirectory}/${project.artifactId}.meta.js</metaFile>
                   </configuration>
                   </execution>
           </executions>
           </plugin>
           <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-jar-plugin</artifactId>
           <version>2.6</version>
           <configuration>
                   <forceCreation>true</forceCreation>
                   <classesDirectory>${project.build.outputDirectory}</classesDirectory>
                   <includes>
                   <include>/*.js</include>
                   <include>
/*.kt</include>
                   </includes>
                   <archive>
                   <forced/>
                   <manifestEntries>
                           <Built-By>${user.name}</Built-By>
                           <Implementation-Vendor>JetBrains s.r.o.</Implementation-Vendor>
                           <Implementation-Version>${project.version}</Implementation-Version>
                           <Specification-Title>???</Specification-Title>
                           <Kotlin-JS-Module-Name>${project.artifactId}</Kotlin-JS-Module-Name>
                   </manifestEntries>
                   </archive>
           </configuration>
           </plugin>
           <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-source-plugin</artifactId>
           <version>2.4</version>
           <executions>
                   <execution>
                   <id>attach-sources</id>
                   <goals>
                           <goal>jar</goal>
                   </goals>
                   </execution>
           </executions>
           </plugin>
  </plugins>
  </build>
</project>

Am I on the right track?
Which generated files are required to be included in the HTML so it can run successfully?

Thanks!

Let me throw something together and send it to you.   

Thanks a lot!

In case you want to use email, my email is: jvskriubakken @ gmail.com

I've attached an example of a Maven project that consists of two modules:

  • Server: Compiles to JVM
  • Client: Compiles to JavaScript

Server is a simple Http servlet that responds to “/hello” with some text. It’s written in Kotlin. The code is in HttpServlet.kt

Client is a simple main routine that uses jQuery to load the text returned by the server in a div. The code is in Main.kt

To run it, start the server and then open the index.html file. Make sure if running under Tomcat that you have CORS enabled.

index.html references a few files: jquery, the output of the compilation of the client module, and the kotlin.js runtime. The Maven pom.xml shows how to define these and also how to unpack the runtime for Kotlin. You can also specifiy where you want the files deployed to.

I’ll provide a more thorough step by step in a tutorial on the kotlin soon, but for now if you have any questions, let us know.

Thanks.



client-server.zip (156 KB)

Thanks a lot Hadi!

I’ve created a small experimental project where I’ve now imiated your setup. You can see it on Github here:
https://github.com/jvskriubakken/kotlin-js

I successfully built your project using maven from my IntellijJ.
However, when I use the same setup as you I get an error when Kotlin maven compiler executes:

/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/bin/java “-Dmaven.home=/Applications/IntelliJ IDEA 14.app/Contents/plugins/maven/lib/maven3” “-Dclassworlds.conf=/Applications/IntelliJ IDEA 14.app/Contents/plugins/maven/lib/maven3/bin/m2.conf” -Didea.launcher.port=7547 “-Didea.launcher.bin.path=/Applications/IntelliJ IDEA 14.app/Contents/bin” -Dfile.encoding=UTF-8 -classpath “/Applications/IntelliJ IDEA 14.app/Contents/plugins/maven/lib/maven3/boot/plexus-classworlds-2.4.jar:/Applications/IntelliJ IDEA 14.app/Contents/lib/idea_rt.jar” com.intellij.rt.execution.application.AppMain org.codehaus.classworlds.Launcher -Didea.version=14.1.2 install
[INFO] Scanning for projects…
[INFO]                                                                   
[INFO] ------------------------------------------------------------------------
[INFO] Building kotlin-js-example 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] — maven-resources-plugin:2.5:resources (default-resources) @ kotlin-js-example —
[debug] execute contextualize
[INFO] Using ‘UTF-8’ encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/joerunds/Code/kotlin-js/kotlin-js-example/src/main/resources
[INFO]
[INFO] — maven-compiler-plugin:2.3.2:compile (default-compile) @ kotlin-js-example —
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] — kotlin-maven-plugin:0.1-SNAPSHOT:js (compile) @ kotlin-js-example —
[info] Kotlin Compiler version 0.11.1008
[info] Compiling Kotlin sources from [/Users/joerunds/Code/kotlin-js/kotlin-js-example/src/main/kotlin]
[info] libraryFiles: [/Users/joerunds/.m2/repository/org/jetbrains/kotlin/kotlin-js-library/0.1-SNAPSHOT/kotlin-js-library-0.1-SNAPSHOT.jar]
[debug] Output:
/Users/joerunds/Code/kotlin-js/kotlin-js-example/target/classes/…/…/js/kotlin-js-example.js
Sources:
/Users/joerunds/Code/kotlin-js/kotlin-js-example/src/main/kotlin/no/logiq/kotlin/hello-world.kt
/Users/joerunds/Code/kotlin-js/kotlin-js-example/src/main/kotlin/no/logiq/kotlin/Task.kt
[error] java.io.FileNotFoundException: /Users/joerunds/Code/kotlin-js/kotlin-js-example/target/classes/…/…/js/kotlin-js-example.js (No such file or directory)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:213)
at com.intellij.openapi.util.io.FileUtil.writeToFile(FileUtil.java:1154)
at com.intellij.openapi.util.io.FileUtil.writeToFile(FileUtil.java:1148)
at com.intellij.openapi.util.io.FileUtil.writeToFile(FileUtil.java:1136)
at org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsPackage$outputUtils$e7c08a89.writeAll(outputUtils.kt:32)
at org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsPackage$outputUtils$e7c08a89.writeAll(outputUtils.kt:43)
at org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsPackage.writeAll(outputUtils.kt:1)
at org.jetbrains.kotlin.cli.js.K2JSCompiler.doExecute(K2JSCompiler.java:192)
at org.jetbrains.kotlin.cli.js.K2JSCompiler.doExecute(K2JSCompiler.java:69)
at org.jetbrains.kotlin.cli.common.CLICompiler.exec(CLICompiler.java:148)
at org.jetbrains.kotlin.maven.KotlinCompileMojoBase.executeCompiler(KotlinCompileMojoBase.java:230)
at org.jetbrains.kotlin.maven.KotlinCompileMojoBase.execute(KotlinCompileMojoBase.java:174)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:320)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
at org.codehaus.classworlds.Launcher.main(Launcher.java:47)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

It’s like it expects kotlin-js-example.js to exist from before?

Ah sorry. It's just I didn't redefine the output directory and it needs to exist. Under kotlin-js-example create the following folders

targetclasses

That should then work (I cloned and verified it with your repo)

Ah, OK.

I used maven-antrun-plugin to ensure that directory target/classes exist before the compile phase:
https://github.com/jvskriubakken/kotlin-js/commit/821bb60935d3c1e427b9a3b85a095f8983b0fabb

I've managed to call some Kotlin-generated Javascript now :) So I think we can call this thread as solved. Thanks for the prompt help! I'll rather ask new questsions in new threads when I run into other problems.

Thanks!
Jørund

Hi again Hadi!

I’ve now managed to get Kotlin to compiled using Maven:
https://github.com/jvskriubakken/kotlin-js

However, when hitting compile in IntelliJ then compiler fails:

Must I set something up in IntelliJ additionally?

And what is the meta.js files used for? They are not needed in HTML?

The Gradle version is using the Snapshot version. Do you have the same one installed in IDEA? Based on the output, don't know full version by memory right now.

For the kotlin-maven-plugin I'm using version 0.1-SNAPSHOT.

Not sure if that’s recommoned, but that was what I saw you where using in your example.

I came around my compile problem in IntelliJ by addding framework support for Kotlin (Javascript) manually on the module, resulting in this orderEntry being added to the IntelliJ module config:
<orderEntry type=“library” name=“KotlinJavaScript” level=“project” />
in addition to the existing:
<orderEntry type=“library” name=“Maven: org.jetbrains.kotlin:kotlin-js-library:0.1-SNAPSHOT” level=“project” />

Should’nt the “framework support” have been added auomatically added to the module by IntelliJ when it synchronises it’s own module configs against maven pom’s?

This is strange. You're using Maven right? So all dependencies should be configured using Maven.

Yes, I do.

I'm also having trouble getting that project to compile (from the command line, using Maven).

My output is:

[sen@theAir kotlin-js]$ mvn compile [INFO] Scanning for projects... [INFO] ------------------------------------------------------------------------ [INFO] Reactor Build Order: [INFO] [INFO] kotlin-javascript [INFO] kotlin-js-example [INFO] kotlin-webapp [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building kotlin-javascript 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building kotlin-js-example 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [WARNING] The metadata /Users/sen/.m2/repository/org/jetbrains/kotlin/kotlin-maven-plugin/0.1-SNAPSHOT/maven-metadata-sonatype.oss.snapshots.xml is invalid: end tag name </body> must match start tag name <hr> from line 5 (position: TEXT seen ...</center>rn</body>... @6:8) [WARNING] The metadata /Users/sen/.m2/repository/org/jetbrains/kotlin/kotlin-maven-plugin/0.1-SNAPSHOT/maven-metadata-sonatype.oss.snapshots.xml is invalid: end tag name </body> must match start tag name <hr> from line 5 (position: TEXT seen ...</center>rn</body>... @6:8) [WARNING] The POM for org.jetbrains.kotlin:kotlin-maven-plugin:jar:0.1-SNAPSHOT is invalid, transitive dependencies (if any) will not be available, enable debug logging for more details [INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary: [INFO] [INFO] kotlin-javascript ................................. SUCCESS [0.004s] [INFO] kotlin-js-example ................................. FAILURE [0.251s] [INFO] kotlin-webapp ..................................... SKIPPED [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] Total time: 0.494s [INFO] Finished at: Wed May 06 19:38:44 CEST 2015 [INFO] Final Memory: 6M/97M [INFO] ------------------------------------------------------------------------ [ERROR] Failed to parse plugin descriptor for org.jetbrains.kotlin:kotlin-maven-plugin:0.1-SNAPSHOT (/Users/sen/.m2/repository/org/jetbrains/kotlin/kotlin-maven-plugin/0.1-SNAPSHOT/kotlin-maven-plugin-0.1-SNAPSHOT.jar): error in opening zip file -> [Help 1]

Any hints? Other than that, very interested in this proof-of-concept project. Thanks for setting it up!

Added link to github project

Very strange. Nothing wrong with the project I think. Still builds successfully my side. Seems like something is wrong with maven or the maven repository. Very strange error message, since it's taling about center tag!??

I’m using Java 8 and Maven 3.2.5

Hmm... with my Ubuntu setup is working. Maybe it works only with Java 8?

Thanks a lot for the project setup. Will be studying it :-)

Is it possible (at least using Maven) to have one setup that generates both client-side JavaScript and server-side JVM output, sharing (some, not all) Kotlin code between the two?

/shared
  (shared classes go here)
/server
  (server-side Kotlin code, makes use or “shared”)
/client
  (client-side Kotlin code, makes use or “shared”)

Ideally where the “server side” would serve the client-side generated JS.

Would such a Maven setup be possible, and doable? Or is that something currently not supported?

Thanks! :slight_smile: