Skip to content
shunter1112 edited this page Sep 14, 2013 · 3 revisions

このクイックスタートはHerokuにデプロイされるJavaとJettyが組み込まれたWebサーバについて扱って行きます。Herokuを使ったアプリケーションの開発と設計の仕方についての一般的な情報は、Architecting Applications for Herokuを確認してください。

{.note} JavaのデモアプリケーションのためのサンプルコードはGitHubで利用可能です。編集や改善は歓迎します。

前提条件

  • 基本的なJavaの知識。JVMのインストールされているバージョンそしてMaven 3を含みます。
  • あなたのアプリケーションはOpenJDK version 6, か 7 (8もベータが利用可能)の上で走っていること
  • Herokuのユーザアカウント。こちらで無料で簡単に取得ができます

ローカルでの開発環境の準備

もしあなたがEclipseのユーザなら、これらのステップを飛ばしてEclipseの開発環境を使って始める事が出来ます。Getting Started with Heroku & Eclipseを見てみてください。

Heroku Toolbeltをローカルにインストール します。これはあなたのHeroku command-line client、Foreman、そしてGitのバージョン管理システムへアクセスを確かなものにします。

一度インストールできると、herokuコマンドがシェルから使えるようになります。アカウントを作ったときに使ったE-mailアドレスやパスワードを使ってログインしてみます :

:::term
$ heroku login
Enter your Heroku credentials.
Email: adam@example.com
Password: 
Could not find an existing public key.
Would you like to generate one? [Yn] 
Generating new SSH public key.
Uploading ssh public key /Users/adam/.ssh/id_rsa.pub

エンターキーをおすとすぐに存在しているsshキーか新しいものをアップロードしてくれます。後でコードをプッシュするときに使います。

アプリケーションの作成

どんなJavaのアプリケーションでもビルドツールであるMavenを使って、Herokuで実行できるようになりました。例として、Jettyを使ったWebアプリケーションを書いてみます。ここにアプリを開始するための基本的なメソッドが含まれている基本的なサーブレットクラスがあります。

src/main/java/HelloWorld.java

:::java
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.*;

public class HelloWorld extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.getWriter().print("Hello from Java!\n");
    }

    public static void main(String[] args) throws Exception{
        Server server = new Server(Integer.valueOf(System.getenv("PORT")));
        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        context.setContextPath("/");
        server.setHandler(context);
        context.addServlet(new ServletHolder(new HelloWorld()),"/*");
        server.start();
        server.join();   
    }
}

pom.xmlに依存関係を宣言

HerokuはJavaのアプリをpom.xmlファイルの存在によって認識します。ここに上で作ったJava/Jettyアプリのためのpom.xmlの例を載せます。

pom.xml

:::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>
    <artifactId>helloworld</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
            <version>7.6.0.v20120127</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
    </dependencies>
    <build>
        <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>
        </plugins>
    </build>
</project>

バージョン管理内に余計なものが含まれてしまわないように、このファイルを作ります :

.gitignore

:::term
target

ローカルでのアプリケーションの作成と実行

ローカルでアプリケーションを作成します :

:::term
$ mvn package

ビルドの一部分として、Mavenは依存性のあるファイルを集めて、target/dependencyの中にコピーします。PORT環境変数を設定し、依存性のあるファイルへのパスを指定しながらJavaを実行してアプリケーションを開始します:

Mac もしくは Linux:

:::term
$ export PORT=5000
$ java -cp target/classes:"target/dependency/*" HelloWorld

(ダブルクォート"*が展開されるのを防ぐために必要です。)

Windows:

:::term
$ set PORT=5000
$ java -cp target\classes;"target\dependency\*" HelloWorld

すると以下のような物が見えてきます :

:::term
2012-01-31 15:51:21.811:INFO:oejs.Server:jetty-7.6.0.v20120127
2012-01-31 15:51:21.931:INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null}
2012-01-31 15:51:21.971:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:5000

ブラウザでアプリを開きます : http://localhost:5000

Procfileでプロセスタイプを宣言

アプリケーションのルートディレクトリの中のテキストファイルであるProcfileを使って、Webdynoを開始するために何のコマンドが実行されるべきかを明示的に宣言します。

Procfileはこのような見た目になります。

:::term
web:    java -cp target/classes:target/dependency/* HelloWorld

(注意: Procfile内ではダブルクォートはいりません。)

(オプションとして)JDKを選択

デフォルトではOpenJDK1.6がインストールされています。ですが、新しいJDKを使う事もできます。使う場合はsystem.propertiesファイルの中にjava.runtime.version=1.7と指定します。

system.propertiesはこのような見た目をしています :

:::term
java.runtime.version=1.7

Java 6, 7, 8(ラムダ式が使えます) のそれぞれで、1.6, 1.7, 1.8(1.8はベータです)を指定することができます。

Gitにアプリケーションを保存

今、私たちはアプリの中に3つの主要な構成要素を持っています。pom.xmlの中のビルド設定と依存関係ファイル、Procfileの中のプロセスタイプ、そしてsrc/main/java/HelloWorld.javaの中にある私たちのアプリのソースです。Gitに追加していきましょう :

:::term
$ git init
$ git add .
$ git commit -m "init"

Herokuへのアプリケーションのデプロイ

(Herokuの)アプリケーションを作成します :

:::term
$ heroku create
Creating stark-sword-398... done, stack is cedar
http://stark-sword-398.herokuapp.com/ | git@heroku.com:stark-sword-398.git
Git remote heroku added

コードをデプロイします :

:::term
$ git push heroku master
Counting objects: 47, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (25/25), done.
Writing objects: 100% (47/47), 10.25 KiB, done.
Total 47 (delta 19), reused 42 (delta 17)

-----> Heroku receiving push
-----> Java app detected
-----> Installing OpenJDK 1.6... done
-----> Installing Maven 3.0.3... done
-----> Installing settings.xml... done
-----> executing /app/tmp/repo.git/.cache/.maven/bin/mvn -B -Duser.home=/tmp/build_3k0p14ghrmdzs -Dmaven.repo.local=/app/tmp/repo.git/.cache/.m2/repository -s /app/tmp/repo.git/.cache/.m2/settings.xml -DskipTests=true clean install
       [INFO] Scanning for projects...
       [INFO]                                                                         
       [INFO] ------------------------------------------------------------------------
       [INFO] Building helloworld 1.0-SNAPSHOT
       [INFO] ------------------------------------------------------------------------
       ...
       [INFO] ------------------------------------------------------------------------
       [INFO] BUILD SUCCESS
       [INFO] ------------------------------------------------------------------------
       [INFO] Total time: 10.062s
       [INFO] Finished at: Tue Jan 31 23:27:20 UTC 2012
       [INFO] Final Memory: 12M/490M
       [INFO] ------------------------------------------------------------------------
-----> Discovering process types
       Procfile declares types -> web
-----> Compiled slug size is 948K
-----> Launching... done, v3
       http://empty-fire-6534.herokuapp.com deployed to Heroku

アプリケーションへの訪問

Herokuにコードをデプロイしました、そしてProcfileの中にプロセスタイプを指定しました。今、あなたはHerokuに対してプロセスタイプを実行するための指示を出す事が出来ます。Herokuは dynoに関連づいたコマンドを実行することでこれを行います。dynoとはHerokuにおける基本的な構成要素の単位になっている軽量コンテナのことです。

webプロセスタイプが実行されているdynoがあることを確かめてみましょう :

:::term
$ heroku ps:scale web=1

アプリケーションのdynoの状態を確認することができます。このheroku psコマンドはあなたのアプリケーションの実行中のdynoをリストします :

:::term
$ heroku ps
=== web: `java -cp target/classes:target/dep...`
web.1: up for 5s

ここにdynoが一つ走っています。

heroku openを使ってブラウザでアプリを確認することができます。

:::term
$ heroku open
Opening empty-fire-6534... done

Dynoのスリープと拡張

実行中のWeb dynoを一つだけ持っている事は、dynoが非アクティブになったあと1時間経つとスリープすることを意味します。これは再度立ち上がるときの最初のリクエストに対して数秒の遅れが発生することを意味します。後続のリクエストは通常通りに帰ってくるでしょう。

これを避けるために、web dynoを1個以上に増やすことが出来ます。例えば :

:::term
$ heroku ps:scale web=2

それぞれのアプリケーションごとに、Herokuは750時間のdyno無料利用時間を提供しています。2個のdynoで動いているアプリケーションは、月々のこの無料利用時間を超える可能性が高いので、増やしたものを戻してみましょう :

:::term
$ heroku ps:scale web=1

ログの確認

Herokuは、アプリケーションの内容物を実行しているすべてのdynoの出力ストリームから時系列イベントのストリームとしてログを扱います。HerokuのLogplexはこれらのイベントの全てをあつかう単体のチャネルを提供しています。

ログ用コマンドの一つを使って、実行中のあなたのアプリケーションの情報を見てみましょう。heroku logs を実行します。 :

:::term
$ heroku logs
2012-01-31T23:27:27+00:00 heroku[web.1]: Starting process with command `java -cp target/classes:target/dependency/* HelloWorld`
2012-01-31T23:27:28+00:00 app[web.1]: 2012-01-31 23:27:28.280:INFO:oejs.Server:jetty-7.6.0.v20120127
2012-01-31T23:27:28+00:00 app[web.1]: 2012-01-31 23:27:28.334:INFO:oejsh.ContextHandler:started o.e.j.s.ServletContextHandler{/,null}
2012-01-31T23:27:28+00:00 app[web.1]: 2012-01-31 23:27:28.373:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:8236
2012-01-31T23:27:29+00:00 heroku[web.1]: State changed from starting to up

次のステップ

  • Spring MVC Hibernate チュートリアルはHerokuのデータベース駆動のアプリケーションを構築するためのガイドになるでしょう。
  • 開発についてとJavaのアプリケーション開発についてより学びたい場合はJavaカテゴリを訪れてみてください。
  • アプリケーションを書いたり、構成したり、デプロイしたり、実行する時に直面するだろう概念について、技術的な大枠を知りたい場合はHerokuの仕組みを読むといいでしょう。
Clone this wiki locally