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が試せる環境があるというのは非常にありがたいことですねぇ。
なんか作ってみたいけれど、どうしたものか…。