Kotlin Advent Calendar 2013で空いていた枠を書くようにしていたんだけれど、
全然書けていなかったので、とりあえず書いておきます。
HerokuでKotlinは動くよ、という報告です。
HerokuはPaaSとして有名ですが、いろんな言語をサポートしています。
Javaもサポートされているので、うまいことすればKotlin動くかなと思っていました。
まず、Heroku Javaのサイトに行きます。
Containerless web app with Embedded Jettyから、Create Appを押してアプリを作ります。
すると、Javaアプリが作られます。
Herokuにログインして、gitリポジトリを確認して、そこからcloneしましょう。
cloneすると、今デプロイされている内容がDLされるので、これを修正していきます。
まず、pom.xmlを修正します。
<?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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <version>1.0-SNAPSHOT</version> <name>helloworld</name> <artifactId>helloworld</artifactId> <packaging>jar</packaging> <properties> <kotlin.version>0.6.1673</kotlin.version> <java.version>1.6</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- Servlet API --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <!-- Jetty --> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-servlet</artifactId> <version>7.6.0.v20120127</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-webapp</artifactId> <version>7.6.0.v20120127</version> </dependency> <dependency> <groupId>org.mortbay.jetty</groupId> <artifactId>jsp-2.1-glassfish</artifactId> <version>2.1.v20100127</version> </dependency> <!-- Kotlin --> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-stdlib</artifactId> <version>${kotlin.version}</version> </dependency> </dependencies> <build> <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory> <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.4</version> <executions> <execution> <id>copy-dependencies</id> <phase>package</phase> <goals><goal>copy-dependencies</goal></goals> </execution> </executions> </plugin> <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>compile</goal> </goals> </execution> <execution> <id>test-compile</id> <phase>test-compile</phase> <goals> <goal>test-compile</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
そして、mavenでライブラリをインストールします。
$mvn clean install
buildのところでkotlinのディレクトリを設定しているので、そこにディレクトリをつくります。
$ cd src/main $ mkdir kotlin $ cd ../ $ mkdir -p test/kotlin
src/main/javaディレクトリの内容をsrc/main/kotlinにコピーして、Kotlinに直します。
package com.example import org.eclipse.jetty.server.Server import org.eclipse.jetty.webapp.WebAppContext public fun main(args : Array<String?>?) { val webappDirLocation = "src/main/webapp/" var webPort : String? = System.getenv("PORT") if (webPort == null || (webPort == "")) { webPort = "8080" } val server = Server(webPort!!.toInt()) val root = WebAppContext() root.setContextPath("/") root.setDescriptor(webappDirLocation + "/WEB-INF/web.xml") root.setResourceBase(webappDirLocation) root.setParentLoaderPriority(true) server.setHandler(root) server.start() server.join() }
package com.example import java.io.IOException import java.util.logging.Logger import javax.servlet.ServletConfig import javax.servlet.ServletException import javax.servlet.ServletOutputStream import javax.servlet.http.HttpServlet import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletResponse class HelloServlet() : HttpServlet() { protected override fun doGet(req : HttpServletRequest?, resp : HttpServletResponse?) { var out : ServletOutputStream? = resp?.getOutputStream() out?.write("Hello Heroku".getBytes()) out?.flush() out?.close() } }
その後、src/main/javaディレクトリを削除します。
あと、デフォルトのindex.jspだと、twitter bootstrapの古いやつを参照しようとしているので、なんとなくいやなのでとりあえず真っ新なhtmlにしてみます。
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Kotlin on Heroku</title> <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> Kotlin on Heroku. </body> </html>
あとは、Procfileを修正します。com.example.Mainを、com.example.ExamplePackageにします。
web: java $JAVA_OPTS -cp target/classes:target/dependency/* com.example.ExamplePackage
準備ができたと思うので、コンパイルしてみましょう。
$ mvn clean install compile
ローカルで試してみましょう。Procfileに書いた感じで実行してみます。
java -cp target/classes:target/dependency/* com.example.ExamplePackage
http://localhost:8080/ と、http://localhost:8080/hello にアクセスして動いたら、OK!
そして、デプロイ。Herokuのリポジトリからcloneしているので、herokuがoriginになっています。
$ git add . $ git commit -m "Kotlinで動くようにしてみた" $ git push origin master
うまくいけば、Heroku側でも動くはず。pushしてもちゃんと動いてない場合は、一度再起動してみましょう。
$ heroku restart
無料でサーバサイドKotlinが試せる環境があるというのは非常にありがたいことですねぇ。
なんか作ってみたいけれど、どうしたものか…。