Skip to content

Spring mvc hibernate

shunter1112 edited this page Sep 14, 2013 · 2 revisions

このチュートリアルはHerokuにデプロイされる、Postgresデータベースサービスを使用した、Spring MVC Hibernate アプリケーションについて扱って行きます。Herokuを使ったアプリケーションの開発と設計の仕方についての一般的な情報は、Architecting Applications for Herokuを確認してください。

{.note} このデモアプリケーションのソースコードはGitHubで利用可能です。編集と改善を歓迎します。リポジトリをフォークして、あなたの変更を追加し、私たちにプルリクエストを送ってください。

事前準備/前提条件

Spring MVC と Hibernate を使ったJavaアプリケーションの作成

まだSpringMVCとHibernateを使ったアプリケーションを持っていない場合は、もっとも簡単に作る方法としてSpring Rooがあります。Spring RooはRADツールで、完全なモデル、ビューそしてコントローラと、リレーショナルデータベースとの統合を含んだSpring MVC アプリケーションの構築を素早く行う事が出来ます。

(オプション1) アンプルアプリケーションのクローン

Spring Roo のインストールをしたくないという方は、サンプルアプリのクローン(複製)をして下さい。

:::term
$ git clone https://github.com/heroku/devcenter-spring-mvc-hibernate.git 
Cloning into petclinic...
remote: Counting objects: 205, done.
remote: Compressing objects: 100% (100/100), done.
remote: Total 205 (delta 93), reused 205 (delta 93)
Receiving objects: 100% (205/205), 98.55 KiB, done.
Resolving deltas: 100% (93/93), done.

これで、完全なアプリケーションをチェックアウトすることができます。スターティングポイントに戻すために以下を実行してください :

:::term
$ git revert starting-point

これで、"データベース設定の変更" の章の前の状態に戻ることができました。

(オプション2) Spring Rooを使ったアプリの作成

もしまだSpring Rooを持っていないようであればインストールしてください。そして、アプリケーションを作成するためのディレクトリを作成し、clinic.rooのスクリプトを使ってアプリを生成します :

:::term
$ mkdir petclinic && cd petclinic
$ roo script --file clinic.roo
    ____  ____  ____  
   / __ \/ __ \/ __ \ 
  / /_/ / / / / / / / 
 / _, _/ /_/ / /_/ /  
/_/ |_|\____/\____/    1.1.4.RELEASE [rev f787ce7]


Welcome to Spring Roo. For assistance press TAB or type "hint" then hit ENTER.
project --topLevelPackage com.springsource.petclinic
Created ROOT/pom.xml
Created SRC_MAIN_JAVA
Created SRC_MAIN_RESOURCES
...
Updated SRC_MAIN_RESOURCES/log4j.properties
Script required 41 second(s) to execute

デフォルトでは、生成されたアプリケーションの設定はメモを使用するHSQLDBを使う様になっています。しかし、ローカルで使うデータベースはプロダクション環境と同じものを使う事を強くおすすめします。そのため、このRooコマンドを使ってPostgresを使うようにアプリケーションを切り替えましょう :

:::term
$ roo persistence setup --provider HIBERNATE --database POSTGRES
...
Updated SRC_MAIN_RESOURCES/META-INF/spring/database.properties
Please update your database details in src/main/resources/META-INF/spring/database.properties.
Updated ROOT/pom.xml [removed dependency org.hsqldb:hsqldb:1.8.0.10; added dependency postgresql:postgresql:8.4-702.jdbc3]
Updated SRC_MAIN_RESOURCES/META-INF/spring/applicationContext.xml
Updated SRC_MAIN_RESOURCES/META-INF/persistence.xml
...

最後に、Gitのリポジトリを作ってアプリケーションに関するこれまでの物をコミットします。

:::term
$ git init
$ echo target > .gitignore
$ git add .
$ git commit -m init

データベース設定の変更

Spring Rooによって生成されたWebアプリケーションは、src/main/resources/META-INF/spring/database.propertiesファイルの中に、データベース接続設定があることを想定しています。しかし、あなたのプロジェクトのどこかのファイルにデータベースの設定をハードコーディングするのは得策ではありません。そのかわりに、環境変数から設定を読み込めるように、Springの設定ファイルを編集します。

Herokuは、Javaアプリケーションを作成した際、自動で小規模なデータベースを準備してくれます。そしてDATABASE_URLという環境変数を以下のフォーマットのURLに従って割り当ててくれます。

postgres://user:password@hostname:port/dbname

同時にheroku addonsコマンドを使って、自分自身でより大きいデータベースのサービスを準備することもできます。どちらの方法にせよ、データベースの接続情報はDATABASE_URLに格納されます。

この環境変数によって初期化される新しいURI spring beanを src/main/resources/META-INF/spring/applicationContext.xml に以下のコードを追加する事で作成します :

:::xml
<bean class="java.net.URI" id="dbUrl">
    <constructor-arg value="${DATABASE_URL}"/>
</bean>

src/main/resources/META-INF/spring/applicationContext.xmlの中のdataSourceの部分を編集し、プロパティタグの属性を以下のように置き換えて行きます :

:::xml
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
    <property name="driverClassName" value="${database.driverClassName}"/>
    <property name="url" value="#{ 'jdbc:postgresql://' + @dbUrl.getHost() + ':' + @dbUrl.getPort() + @dbUrl.getPath() }"/>
    <property name="username" value="#{ @dbUrl.getUserInfo().split(':')[0] }"/>
    <property name="password" value="#{ @dbUrl.getUserInfo().split(':')[1] }"/>
    ...

アプリケーションをローカルで実行するために、DATABASE_URL変数をローカル環境で、ローカルのpostgresを参照できるように設定します。例えば以下のようになります :

:::term
$ export DATABASE_URL=postgres://scott:tiger@localhost:5432/myapp

Jetty Runner の追加

Jetty RunnerはあなたのWebアプリケーションを標準的なJavaアプリケーションとして実行することを可能にします。(コンテナにデプロイする必要はありません) これは単純なjarファイルで、中心となるMavenのリポジトリからあなたのビルドの指定するディレクトリにコピーすることがことができます。これを行うために、pom.xmlpluginsセクションの最後に以下のプラグイン設定を追加することで、maven-dependency-pluginを使います :

:::xml
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.3</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals><goal>copy</goal></goals>
            <configuration>
                <artifactItems>
                    <artifactItem>
                        <groupId>org.mortbay.jetty</groupId>
                        <artifactId>jetty-runner</artifactId>
                        <version>7.4.5.v20110725</version>
                        <destFileName>jetty-runner.jar</destFileName>
                    </artifactItem>
                </artifactItems>
            </configuration>
        </execution>
    </executions>
</plugin>

Procfileへのプロセスタイプの宣言

アプリケーションのルートディレクトリにあるテキストファイルであるProcfileを使って、Web Dynoを開始させるために何のコマンドを実行するべきかを明示的に宣言します。この場合は、Jetty Runnerを実行する必要があります。

これは私たちがいま扱っているサンプルアプリのためのProcfileです :

:::term
web: java $JAVA_OPTS -jar target/dependency/jetty-runner.jar --port $PORT target/*.war

これは、1個のwebプロセスタイプと実行する必要のあるコマンドを宣言しています。"web"と付けることはここではとても重要です。これは、このプロセスタイプがHerokuのHTTPルーティングのスタックに積まれ、デプロイされた際にWebトラフィックを受け付けることを意味しています。

(オプション) JDKの選択

デフォルトでは、アプリケーションにOpenJDK 1.6がインストールされます。しかし、system.propertiesファイル内にjava.runtime.version=1.7と指定することで新しいバージョンのJDKを使う事ができます。

ここにsystem.propertiesがどのような見た目なのかを示します :

:::term
java.runtime.version=1.7

同様に、それぞれJava6, 7, または8(ラムダ構文)に対して1.6, 1.7, 1.8(1.8はベータ)を指定する事ができます。

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

すべてが動くかどうか確かめるために、まず始めにアプリケーションをローカルで実行してみましょう。Postgresデータベースを立ち上げ、上記で指定したDATABASE_URLがアクセス可能な状態になっている必要があります。

アプリケーションのビルド

:::term
$ mvn package
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building petclinic 0.1.0.BUILD-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
...
[INFO] --- maven-dependency-plugin:2.3:copy (default) @ petclinic ---
[INFO] Configured Artifact: org.mortbay.jetty:jetty-runner:7.4.5.v20110725:jar
[INFO] Copying jetty-runner-7.4.5.v20110725.jar to /Users/jjoergensen/dev/tmp/spring-roo-petclinic/target/dependency/jetty-runner.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 20.466s
[INFO] Finished at: Mon Aug 29 20:56:03 PDT 2011
[INFO] Final Memory: 9M/81M
[INFO] ------------------------------------------------------------------------

アプリケーションの開始

Note: you can also start your app using foreman to execute the Procfile. [Read more about foreman and Procfiles](http://devcenter.heroku.com/articles/procfile).
:::term
$ java -jar target/dependency/jetty-runner.jar target/*.war

アプリケーションの確認

http://localhost:8080 へ飛び、新しいレコードを追加するなどして動作確認してみましょう。

アプリケーションのGitへの格納

これで、私たちはアプリケーションとpom.xmlの中で宣言しているその依存ファイル、そしてProcfileが揃いました。Gitの中にこれらを置いてみましょう :

:::term
$ git add .
$ git commit -m "Ready to deploy"

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

アプリケーションの作成 :

:::term
$ heroku create
Creating high-lightning-129... done, stack is cedar
http://high-lightning-129.herokuapp.com/ | git@heroku.com:high-lightning-129.git
Git remote heroku added

コードをデプロイ :

:::term
$ git push heroku master
Counting objects: 227, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (117/117), done.
Writing objects: 100% (227/227), 101.06 KiB, done.
Total 227 (delta 99), reused 220 (delta 98)

-----> Heroku receiving push
-----> Java app detected
-----> Installing Maven 3.0.3..... done
-----> Installing settings.xml..... done
-----> executing .maven/bin/mvn -B -Duser.home=/tmp/build_1jems2so86ck4 -s .m2/settings.xml -DskipTests=true clean install
       [INFO] Scanning for projects...
       [INFO]                                                                         
       [INFO] ------------------------------------------------------------------------
       [INFO] Building petclinic 0.1.0.BUILD-SNAPSHOT
       [INFO] ------------------------------------------------------------------------
       ...
       [INFO] ------------------------------------------------------------------------
       [INFO] BUILD SUCCESS
       [INFO] ------------------------------------------------------------------------
       [INFO] Total time: 36.612s
       [INFO] Finished at: Tue Aug 30 04:03:02 UTC 2011
       [INFO] Final Memory: 19M/287M
       [INFO] ------------------------------------------------------------------------
-----> Discovering process types
       Procfile declares types -> web
-----> Compiled slug size is 62.7MB
-----> Launching... done, v5
       http://pure-window-800.herokuapp.com deployed to Heroku

おめでとうございます!これであなたのアプリケーションは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 $JAVA_OPTS -jar target/dependency/jetty-runner.jar --port $PORT target/*.war`
web.1: up for 6m

ここでは、1個のDynoが実行中です。

heroku openを使うとブラウザからアプリケーションへ訪問することができます。

:::term
$ heroku open
Opening pure-window-800... done

Dynoのスリープと拡張

実行中のWeb Dynoが1個のしかない場合、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はこれらの全てのイベントのための単体のチャンネルを提供します。

あなたの実行中のアプリケーションに関する情報を、logging commandsの一つである heroku logs を使ってみてみましょう :

:::term
$ heroku logs
...
2012-09-11T19:12:27+00:00 app[web.1]: 2012-09-11 19:12:27,217 [main] INFO org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'petclinic': initialization completed in 573 ms
2012-09-11T19:12:27+00:00 app[web.1]: 2012-09-11 19:12:27.240:INFO::Started SelectChannelConnector@0.0.0.0:38895 STARTING
2012-09-11T19:12:28+00:00 heroku[web.1]: State changed from starting to up

次のステップ

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