掲示板アプリケーション
それでは実際に、Heroku Postgresにアクセスするアプリケーションを動かしてみます。
今回は、前回作成したアプリケーションのGitHubの「03」というブランチにシンプルな掲示板アプリケーションを作成してみました。 前回からの主な変更点は以下のとおりです。
- 「/」に割り当てていたHelloServletを「/hello」に変更
- 「/」にインデックスページ(IndexServlet)を追加
- 「/board」に掲示板(BoardServlet)を追加
- Database.java(https://github.com/shunjikonishi/codezine-sample/blob/03/src/main/java/jp/codezine/sample/heroku/util/Database.java)としてDATABASE_URLからJDBCのConnectionを生成するユーティリティクラスを追加
完全なDiff(差分)をGitHub上で見ることもできます。
Javaアプリケーションのコード解説を行うことは本稿の趣旨から外れるので、詳細な説明は割愛しますが、Database.javaに、postgresスキームをjdbcスキームに変換する処理が記述されているので参考にしてください。
Connectionさえ取得できれば、あとは通常のJDBCプログラミングです。
なお、このアプリケーションは、実際にHeroku上で公開しています。ブラウザからアクセスしてご覧ください。
実際には多くの言語、フレームワークがpostgresスキーム形式の文字列を直接使用して接続することができます。 Javaを使用する場合でもHibernateやPlayframeworkではpostgresスキームをサポートしているので、自力でpostgresスキームをjdbcスキームに変換する必要に迫られることはそれほど多くはないでしょう。それでも、フレームワークが背後で同じことをしていることは理解しておいて損はないです。
GitHubからのコード取得
前回作成したアプリケーションのディレクトリに移動して、以下のコマンドを実行してください。
$ git fetch upstream $ git branch 03 upstream/03 $ git checkout 03
git fetchはupstream(サンプルコードを保管しているoriginリポジトリへの参照名。前回設定しました)からリポジトリの内容を取得するコマンド、git branchはupstreamの03ブランチからローカルに03ブランチを作成するコマンド、git checkoutはローカルのブランチを切り替えるコマンドです。
コマンド実行後にディレクリ内を確認すると、Database.javaやBoardServlet.javaなど今回作成したファイルが追加されていることがわかります。
とりあえずコンパイルしてローカル実行
まずは前回同様コンパイルして、ローカル環境でアプリケーションを実行してみます。
$ mvn package $ ./run.sh (Windowsの場合は「run」)
実行後にブラウザで「http://localhost:5000」にアクセスするとインデックスページが表示されます。 「掲示板」のリンクをクリックすると掲示板アプリケーションのページに遷移しますが、今はまだデータベースの設定をしていないのでエラーになるはずです。
ローカルにデータベースを用意する
このアプリケーションでは、環境変数DATABASE_URLから接続情報を取得してデータベース接続を行っています(Database.javaを参照)。 つまり、ローカル環境でもこの環境変数に接続可能なデータベース情報を設定する必要があります。
ローカルホスト上でPostgreSQLが実行されている場合は、環境変数の設定は以下のようになります(環境によってユーザ名、パスワード、DB名などは異なります)。
Macの場合
$ export DATABASE_URL=postgres://foo:bar@localhost:5432/postgres
Windowsの場合
$ set DATABASE_URL=postgres://foo:bar@localhost:5432/postgres
接続可能であればPostgreSQLは異なるホスト上で動作していても構いません。 あるいはローカルからでもHeroku Postgresに直接接続することも可能です。
$ export DATABASE_URL=postgres://xazxehmuvqeurc:-4XWLr17qoATDG0ftW2lC2ld-8@ec2-54-225-136-187.compute-1.amazonaws.com:5432/deflc9ag02nkfu?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory
Heroku Postgresに外部から接続する際にはSSLが必須なので、heroku configで取得した接続情報の後ろにクエリパラメータとしてSSLの設定が付加されていることに注意してください。 ただし、Heroku Postgresは物理的にはアメリカ東海岸にあるので日本から接続した場合は非常に遅いです。
ローカル用のデータベースが用意できたら、psqlやpgAdminなどのSQLツールを使用してcreate.sqlの内容を実行してください。
ここまでですべての準備が整ったので、再びブラウザで「http://localhost:5000/board」にアクセスすると今度は掲示板の画面が表示され、操作もできるはずです。
今回のサンプルコードでは、postgresスキーム以外のDATABASE_URLをはじいているためできませんが、DATABASE_URLを適切に設定すればローカル環境ではPostgreSQLの代わりにSqlLiteやH2などの軽量データベースを使用することも可能です。 ただ、ローカルとHerokuで異なるデータベースを使用すると、一方でのみ発生するエラーに悩まされるリスクが高まります。実際の開発時には、極力マイナーバージョンまで合わせたPostgreSQLを用意するほうが望ましいです。
create.sqlに含まれるCREATE文には「COLLATE "C"」という見慣れないキーワードが含まれていることに気がついた人がいるかと思います。 これは文字列カラムのロケールの設定です。
このロケールの設定はcreatedb時に適切に行っていれば、いちいちCREATE TABLE時に指定する必要はないのですが、Heroku Postgresでは「en_US.UTF-8」固定になっており変更することができません。 このため、「COLLATE "C"」をつけずに作成した文字列カラムに日本語を入れた場合、その列でのORDER BYが正しく行われません。
逆にいえば、ソートに使用しない列や日本語を使用しない列では設定不要なのですが、必要なカラムにつけ忘れて後からハマることも多いので、varcharやtextなどの文字列カラムでは常に指定するようにしたほうが無難です。
(「COLLATE "C"」はALTER TABLEで後から付加することもできます)