HerokuでKotlin動くよという話 #kotlin

Kotlin Advent Calendar 2013で空いていた枠を書くようにしていたんだけれど、
全然書けていなかったので、とりあえず書いておきます。
HerokuでKotlinは動くよ、という報告です。

HerokuはPaaSとして有名ですが、いろんな言語をサポートしています。
Javaもサポートされているので、うまいことすればKotlin動くかなと思っていました。

まず、Heroku Javaのサイトに行きます。
Containerless web app with Embedded Jettyから、Create Appを押してアプリを作ります。
すると、Javaアプリが作られます。

Herokuにログインして、gitリポジトリを確認して、そこからcloneしましょう。
heroku

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


カテゴリー Java, Kotlin | タグ | パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です