【Perl】 Catalystで簡単なWebアプリケーションを作成する
投稿日: / 更新日:
この記事は2年以上前に書かれたものです。情報が古い可能性があります。
今回は、Perlの代表的なWebフレームワークであるCatalystを使って、Hinemosの直近のイベント履歴をJSON形式で取得するサンプルアプリケーションを作成してみます。
なお、アプリケーションの仕様は、http://localhost:3000/event/N/
へHTTP-GETすると、直近”N”件のイベント履歴(未確認のもの)をHinemosDBから取得してJSONとして返す、という非常に簡単なものです。以下に、大まかな手順を記します。
2012/01/16 11:00追記 コントローラにロジックを詰め込み過ぎていたので、ロジックを処理するためのモデルクラスへ分離しました。
1. 必要なモジュール
まず、Perlの実行環境に加えて、以下のCPANモジュールをあらかじめインストールしておきます。
1 2 3 4 5 6 |
Task::Catalyst DBIx::Class::Schema::Loader Catalyst::View::JSON JSON::XS DateTime::Format::Pg |
2. アプリケーションのスケルトンを作成
Catalystインストール時に併せてインストールされる、catalyst.pl
というスクリプトを実行すると、アプリケーションのスケルトンを生成することができます。ここでは、アプリケーションのパッケージ名をHinemosWS::Lite
とします。以下は、スクリプトを実行している様子です。
1 2 3 4 5 6 7 8 9 |
[atomitech@node02 catalyst]$ catalyst.pl HinemosWS::Lite created "HinemosWS-Lite" created "HinemosWS-Lite/script" created "HinemosWS-Lite/lib" (中略) created "HinemosWS-Lite/script/hinemosws_lite_test.pl" created "HinemosWS-Lite/script/hinemosws_lite_create.pl" Change to application directory and Run "perl Makefile.PL" to make sure your install is complete |
3. モデルを作成
まず、モデルクラスを作成します。先ほど生成されたスケルトンの中に、hinemosws_lite_create.pl
というヘルパースクリプトが含まれており、これを使用することでモデルクラスを生成することができます。
モデルクラスの生成は2段階に分かれます。まず、HinemosDBのスキーマを解析してPerlのオブジェクトとして扱うためのスキーマクラスを生成します。以下は、ヘルパースクリプトを実行してスキーマクラスを生成している様子です。
1 2 3 4 5 6 7 |
[atomitech@node02 HinemosWS-Lite]$ ./script/hinemosws_lite_create.pl model DB DBIC::Schema HinemosWS::Lite::Schema create=static 'dbi:Pg:dbname=hinemos;host=localhost;port=24001' hinemos hinemos pg_enable_utf8=1 exists "/home/atomitech/Programs/dev/perl/catalyst/HinemosWS-Lite/script/../lib/HinemosWS/Lite/Model" (中略) Schema dump completed. created "/home/atomitech/Programs/dev/perl/catalyst/HinemosWS-Lite/script/../lib/HinemosWS/Lite/Model/DB.pm" created "/home/atomitech/Programs/dev/perl/catalyst/HinemosWS-Lite/script/../t/model_DB.t" |
この作業により、HinemosDBのスキーマを解析して、各テーブルやカラム、行をPerlのオブジェクトとして扱うためのクラス群が自動生成されます。
続いて、DBからイベント履歴を取得するためのロジックを記述するモデルクラス(のスケルトン)を生成します。
1 2 3 4 5 6 |
[atomitech@node02 HinemosWS-Lite]$ ./script/hinemosws_lite_create.pl model Event exists "/home/atomitech/Programs/dev/perl/catalyst/HinemosWS-Lite/script/../lib/HinemosWS/Lite/Model" exists "/home/atomitech/Programs/dev/perl/catalyst/HinemosWS-Lite/script/../t" created "/home/atomitech/Programs/dev/perl/catalyst/HinemosWS-Lite/script/../lib/HinemosWS/Lite/Model/Event.pm" created "/home/atomitech/Programs/dev/perl/catalyst/HinemosWS-Lite/script/../t/model_Event.t" |
生成したHinemosWS::Lite::Model::Event
クラスには、後述の手順でロジックを追加します。
4. ビューを作成
次に、ビュークラスを作成します。こちらも先ほどと同様、ヘルパースクリプトを使用します。このクラスは、DBから取得したデータをJSONとして出力するためのものです。以下は、ヘルパースクリプトを実行してビュークラスを生成している様子です。
1 2 3 4 5 6 |
[atomitech@node02 HinemosWS-Lite]$ ./script/hinemosws_lite_create.pl view Event JSON exists "/home/atomitech/Programs/dev/perl/catalyst/HinemosWS-Lite/script/../lib/HinemosWS/Lite/View" exists "/home/atomitech/Programs/dev/perl/catalyst/HinemosWS-Lite/script/../t" created "/home/atomitech/Programs/dev/perl/catalyst/HinemosWS-Lite/script/../lib/HinemosWS/Lite/View/Event.pm" created "/home/atomitech/Programs/dev/perl/catalyst/HinemosWS-Lite/script/../t/view_Event.t" |
生成したHinemosWS::Lite::View::Event
クラスには、後で(ほんの少しだけ)手を加えます。
5. コントローラを作成
続いて、コントローラクラスを作成します。このクラスがリクエストURIやパラメータ等を解析し、あらかじめ定義したアクションへ処理をディスパッチする役目を持ちます。以下は、ヘルパースクリプトを実行してコントローラクラスを生成している様子です。
1 2 3 4 5 6 |
[atomitech@node02 HinemosWS-Lite]$ ./script/hinemosws_lite_create.pl controller Event exists "/home/atomitech/Programs/dev/perl/catalyst/HinemosWS-Lite/script/../lib/HinemosWS/Lite/Controller" exists "/home/atomitech/Programs/dev/perl/catalyst/HinemosWS-Lite/script/../t" created "/home/atomitech/Programs/dev/perl/catalyst/HinemosWS-Lite/script/../lib/HinemosWS/Lite/Controller/Event.pm" created "/home/atomitech/Programs/dev/perl/catalyst/HinemosWS-Lite/script/../t/controller_Event.t" |
生成したHinemosWS::Lite::Controller::Event
クラスには、モデルのロジックを呼び出す処理を後ほど追加します。
6. モデルクラスを修正
上記3.の手順で生成したモデルクラスのモジュールファイル(lib/HinemosWS/Lite/Model/Event.pm
)へ、以下のコードを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
sub get_recent { my ($self, $db, $count) = @_; my $rs_events = $db->resultset('CcEventLog')->search({ confirm_flg => 0, }, { rows => ($count > 10 ? 10 : $count), order_by => { -desc => 'generation_date' }, }); my $events = []; my $no = 1; while (my $rs_event = $rs_events->next) { push $events, { no => $no++, generation_date => $rs_event->generation_date->datetime, monitor_id => $rs_event->monitor_id, facility_id => $rs_event->facility_id, priority => $rs_event->priority, message => $rs_event->message, }; } return $events; } |
上記は、HinemosDBのイベント履歴テーブルからデータを取得する処理の本体になります。なお、HinemosDBへの負荷を考慮し、ここでは取得件数を最大10件に制限しています。
7. コントローラを修正
上記5.の手順で生成したコントローラクラスのモジュールファイル(lib/HinemosWS/Lite/Controller/Event.pm
)へ、以下のコードを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
sub get_recent_events :Path :Args(1) { my ($self, $c, $count) = @_; if ($count !~ /^\d+$/xms) { $c->response->body('Invalid argument for event count'); $c->response->status(403); $c->detach; } $c->stash( events => $c->model('Event')->get_recent( $c->model('DB'), $count ) ); $c->forward($c->view('Event')); } |
なお、上で追加したサブルーチンをアクションと呼びます。このアクションでは、URIの最後尾に指定した件数を上限として、モデルクラスを通してHinemosDBのcc_event_log
テーブルから未確認イベントを出力日時の新しい順に取得し、ビューへ渡します。ここでは、PerlのO/RマッピングフレームワークであるDBIx::Classを使用して、生のSQLを全く書かずにデータを取得し、そのままPerlのオブジェクトとして扱っています。
なお、件数の部分に数値以外の文字列を指定した場合は、不正な引数とみなして403を返します。
8. ビューを修正
上記4.の手順で生成したビュークラスのモジュールファイル(lib/HinemosWS/Lite/View/Event.pm
)へ、以下のコードを追加します。
1 2 3 4 5 6 7 8 |
use JSON::XS (); sub encode_json { my ($self, $c, $data) = @_; JSON::XS->new->pretty->encode($data); } |
これにより、コントローラから渡されたオブジェクトをJSON化する際にインデントを付けて整形します。
9. Catalystサーバを起動
以上で準備が整ったので、早速Catalystの開発用サーバを起動します。コマンドは以下のとおりです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[atomitech@node02 HinemosWS-Lite]$ ./script/hinemosws_lite_server.pl -r [debug] Debug messages enabled [debug] Statistics enabled (中略) [debug] Loaded Path actions: .-------------------------------------+--------------------------------------. | Path | Private | +-------------------------------------+--------------------------------------+ | / | /index | | /... | /default | | /event/ | /event/index | | /event/* | /event/get_recent_events | '-------------------------------------+--------------------------------------' [info] HinemosWS::Lite powered by Catalyst 5.90007 HTTP::Server::PSGI: Accepting connections at http://0:3000/ |
端末上に上記のような出力があれば(かつ、エラーが出力されていなければ)、起動は成功です。
10. 動作確認
別の仮想端末からサーバにアクセスして、JSONを取得してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
[atomitech@node02 ~]$ wget -O - http://localhost:3000/event/5/ --2012-01-16 02:26:36-- http://localhost:3000/event/5/ localhost をDNSに問いあわせています... 127.0.0.1 localhost|127.0.0.1|:3000 に接続しています... 接続しました。 HTTP による接続要求を送信しました、応答を待っています... 200 OK { "events" : [ { "priority" : 3, "generation_date" : "2012-01-16T01:06:05", "facility_id" : "node02.local", "monitor_id" : "MON-AGENT", "no" : 1, "message" : "Hinemosジョブエージェントは利用可能です\nHinemosログ転送エージェントは利用可能です" }, (中略) { "priority" : 3, "generation_date" : "2012-01-16T01:05:00", "facility_id" : "node02.local", "monitor_id" : "MON-RES-CPU", "no" : 5, "message" : "CPU使用率 : 0.5" } ] } |
無事、HinemosDBから直近のイベント履歴を5件取得できました。出力されたJSONは、見栄えよく整形されていることが分かります。また、取得件数の代わりに文字列(blah)を指定すると、
1 2 3 4 5 6 7 |
[atomitech@node02 ~]$ wget -O - http://localhost:3000/event/blah/ --2012-01-16 02:28:12-- http://localhost:3000/event/blah/ localhost をDNSに問いあわせています... 127.0.0.1 localhost|127.0.0.1|:3000 に接続しています... 接続しました。 HTTP による接続要求を送信しました、応答を待っています... 403 Forbidden 2012-01-16 02:28:12 エラー 403: Forbidden。 |
意図したとおり、403が返されることが確認できました。
以上、Catalystを使用して簡単なWebアプリケーションを作成する方法をご紹介しました。Catalystを使うことで、このように非常に少ない手間でWebアプリケーションを作成することができます。機会があれば、もう少し複雑なWebアプリケーションについてもご紹介したいと思います。