レベル: 中級 Kristopher William Zyp (kriszyp@xucia.com), Software Developer, Xucia
2007年 11月 13日 Persevere は、永続オブジェクトとブラウザーの JavaScript 環境とのマッピングを実現する永続オブジェクトのフレームワークです。オブジェクトの永続化が Java™ プログラミングと Ruby の世界で絶大な人気を博したことからわかるように、オブジェクトと永続データとのマッピングに適しているのは当然、動的 JavaScript 言語です。Persevere は Ajax (Asynchronous JavaScript + XML) をベースとした Web アプリケーションでのマッピングと通信を自動化するだけでなく、管理可能なデータ・モデルを提供し、透過的なクライアント・サーバー間の Ajax 交換、状態変更の自動保存、そして暗黙的トランザクション管理を行うことによって開発作業の手間を大幅に省きます。
すべてのアプリケーションは実質的に何らかの形で永続性を利用します。つまり、今後の実行に備えて情報を保存するわけです。一般に、アプリケーションには情報を後で取得できるように保持する機能が不可欠であり、Web アプリケーションがますますユーザーからの対話と貢献を組み込むようになるにつれ、永続性は一層重要になってきます。その一方、永続性のためには、プログラムを実行する際のデータのあり方とは概念的に異なる形式で状態情報を保存しなければならないことも珍しくありません。
状態情報は、プログラムの実行においてはオブジェクトに保存されるのが一般的ですが (少なくともオブジェクト指向のプログラムではそれが通常です)、永続化されるときにはデータベース形式になったり、あるいはテキスト・ベースやキャラクター・ベースの形式になったりします。状態情報をこの 2 つのパラダイムの間で変換するには、たいてい大々的な開発作業が必要になり、したがってエラーが発生する可能性も非常に高くなります。そこで、永続オブジェクトのマッピング・ストラテジーでは状態の保存と取得を自動化する手段としてオブジェクトを永続データにマッピングします。このようなマッピングにより、永続状態にアクセスしてその状態を保存する単純なメカニズムを実現することもできます。
 |
情報の保持 Web 2.0 アプリケーションには、情報を後で取得できように保持する機能が不可欠です。Persevere 永続オブジェクトのフレームワークについて学んで、このフレームワークが Ajaxベースの Web アプリケーションでマッピングと通信を自動化する仕組みを理解してください。 |
|
永続オブジェクトの操作を管理しやすくする永続性マッピングは、他の言語 (Ruby on Rails の Active Record や Java 言語の Hibernate など) では非常によく使われています。しかし Ajax ベースのアプリケーションの場合にはデータをシリアライズしてサーバーに送り返す必要があるため、ブラウザーでデータから取得した情報を保存するプロセスがなおさら複雑になります。さらにサーバーは取得したデータをその永続ストアに保存するというプロセスを実行しなければなりません。
この保存プロセス全体を自動化して永続性を一層単純化するのが、直交永続性です。永続的にマッピングされたオブジェクトに対する変更はすべて自動的に永続ストレージに伝搬されるため、手作業で保存する必要はありません。
ツール
この記事では、直交永続性をサポートする JavaScript 言語対応のリモート永続オブジェクトのマッピング・フレームワークである、Persevere JavaScript フレームワークの使用方法を紹介します。永続性対応 JSON (JSPON: JavaScript Object Notation for persistence) 仕様に準拠した Persevere は、JSON (JavaScript Object Notation) と標準 REST (Representational State Transfer) HTTP メソッドを使って JavaScript オブジェクトをリモート側の永続データ・ストアにマッピングします。記事ではさらに、データベースとその他の永続ストアを JSON REST サービスとして公開するプロセスを自動化する Persevere サーバーと Persevere JavaScript クライアントを連動させて使用する方法についても説明します。Persevere を使用すれば、ブラウザーで JavaScript オブジェクトにアクセスして変更するだけで、サーバー上のデータにアクセスし、変更することが可能になります。必要なシリアライズ、Ajax 呼び出し、そしてデシリアライズは、Persevere が自動化します。
この記事に付属のデモは、JavaScript コードの永続オブジェクトのマッピングを使用して単純なブログを作成する方法を実演するためのものです。ブログを作成するには、Persevere クライアント・フレームワークを Persevere サーバーと組み合わせて使用します。Persevere によって、通常の JavaScript オブジェクトとプロパティーを使って永続データにアクセスし、操作することが可能になります。Persevere サーバーがデフォルトのオブジェクト・データベース・ストレージとして指定するのは、お使いの永続データ・ソースです。また、Persevere サーバーはデータベースを Persevere クライアントとサーバー間の通信に使用する JSON フォーマットにサーバー上でマッピングします。永続オブジェクトのマッピングを利用したオブジェクトのアクセスと変更作業の大部分は、単純な JavaScript コードと API を使って行います (「参考文献」セクションに、この記事で使用するすべてのツールへのリンクを記載しています。また、blog.zip パッケージは「ダウンロード」セクションからダウンロードすることができます)。図 1 に、この永続 SOA (Service-Oriented Architecture) を図解します。
図 1. Persevere による永続 JSON SOA
注: Persevere は、persistentjavascript.org で定義された JavaScript の永続性対応オープン API を実装します (「参考文献」にリンクを記載)。
開始手順
まず始めに、Persevere をダウンロードしてセットアップしてください (ファイルへのリンクは「参考文献」に記載)。Persevere サーバーにはクライアントが付属しているので、ダウンロードする必要があるのは Persevere サーバーだけです。Persevere サーバーは Apache Tomcat をすぐに実行できる状態でダウンロードすることも、J2EE (Java 2 Platform, Enterprise Edition) Web アプリケーションとしてダウンロードすることもできます。Tomcat システムをダウンロードした場合は、bin フィルダーから startup を実行するとサーバーが起動します。
永続化されたオブジェクト・グラフを使用してオブジェクトにアクセスし、変更を行うと、変更内容が保持されます。Persevere に付属の永続オブジェクト・ブラウザー (JSPON ブラウザー) は、この作業専用に使用することができます。さらに、Persevere サーバーは動的に拡張可能なオブジェクトの永続ストレージをサポートするので、ブログを生成するためにテーブルを作成する必要はありません。ブログの作成を開始するには、ブラウザーを開き (デフォルトの Tomcat の設定を使用している場合は http://localhost:8080/browser.html)、図 2 に示すブログ配列オブジェクトを作成します (このブログ・オブジェクトを root オブジェクトのプロパティーにしようと思います)。
図 2. ブログ配列オブジェクトの作成
 |
Persevere の永続化機能を使用する方法 Persevere の永続化機能を使用するには何通りかの方法があります。事前処理が必要になるのは、標準 JavaScript プロパティー構文によってプロパティーの遅延ローディングをサポートする場合、そしてプロパティーの変更を自動的に保存する場合のみです。ただし、明示的な保存機能および明示的な遅延ローディング機能による完全な永続性オブジェクト・マッピングの場合は、Persistent JavaScript API を使用して事前処理する必要はありません。さらに、実動アプリケーションで最大限のパフォーマンスを達成するためにサーバー上、またはビルド中に事前処理を行うことも可能です。別の方法としては JavaScript V1.7 (Firefox V2.0 以降) ですべての機能を使って (事前処理を行わずに) Persevere をネイティブに実行したり、JavaScript V1.7 をサポートしないブラウザーに事前処理を適用することもできます。これらの開発手段とビルド・プロセスの使用方法についての詳細は、Persevere の資料 (「参考文献」にリンクを記載) を参照してください。 |
|
root オブジェクトは固定されたオブジェクトで、ここから動的オブジェクト・データベースのすべての永続化されたオブジェクト・グラフにアクセスすることができます。その方法は以下のとおりです。
- ブラウザーで http://localhost:8080/browser.html?id=root を開きます (または、http://localhost:8080/browser.html を開き、Load New Object をクリックして root と入力することもできます)。
- New Property をクリックして、root オブジェクトにプロパティーを追加します。フィールド名を blog として配列オブジェクトを作成します。このオブジェクトは単にブログ投稿のリストを表すだけです。
- ブログ・オブジェクトをクリックして New Property をクリックし、プロパティー名として name を選択してからブログの名前を入力します。
- 変更内容を保存します。
永続性対応の JavaScript コード
永続オブジェクトにアクセスするには Persevere フレームワークを使用します。Persevere フレームワークを使って JavaScript コードを事前に処理し、このコードに遅延ローディングと直交永続性サポートを追加する必要がありますが、そのもっとも簡単な方法は、persevere.loadScript を呼び出して JavaScript ファイルをロードすることです (その他の方法については、囲み記事「Persevere の永続化機能を使用する方法」を参照してください)。Persevere では拡張子に (.js ではなく) .pjs を使い、ファイルが JavaScript ファイルであること、そして永続性を完全にサポートすることを示しています。この拡張子が指定されていれば、loadScript() 関数が必要な処理を行います。
このサンプルでは、クライアント上で事前処理を行うデフォルトの loadScript 機能を使います。直交永続性の機能を例証するには、ブログの名前を変更する下記関数 (リスト 1 を参照) を作成することもできます。
リスト 1. 1本のブログを投稿するための HTML コードの作成
function changeBlogName(blog) {
blog.name = prompt("Enter a new name for our blog");
}
|
ブログの作成
次に、ブログで新しい投稿を生成するための単純な HTML/JavaScript インターフェースを作成します。そのためにはまず blog.html という名前のファイルを作成し、Web アプリケーションのルート・ディレクトリー (デフォルトの Tomcat システムでは webapps/ROOT/) に配置してください。続いて、すべての永続性に対応した JavaScript コードで blog.pjs という名前のファイルを作成します。リスト 2 に、サンプル・ブログ・アプリケーションの HTML コードを記載します。
リスト 2. blog.html
<html>
<head>
<script src="js/persevere.js"></script> <!--include the persistence framework -->
<link rel="stylesheet" type="text/css" href="blog.css"/>
</head>
<body>
<a href="#" onclick="renderBlog()">Home</a>
<div id="blogDiv"></div> <!-- we render the blog in this div later -->
<div id="newPost">
<h3>Enter a new post</h3>
<div>
Content:<textarea id="newPostContent">new post</textarea>
</div>
<button onclick="addBlogPost()">Post</button>
</div>
<script>
persevere.loadScript("blog.pjs");
</script>
</body>
</html>
|
今度は blog.pjs に新規投稿を追加する単純なJavaScript 関数を作成します。新しい投稿を追加すると、その投稿を表す JavaScript オブジェクトが新規に作成されるので、その新規投稿を永続化されたブログ配列オブジェクトに追加します。ほとんどの作業は標準 JavaScript コードで行いますが、ブログ・オブジェクトにアクセスするには root オブジェクトを取得しなければなりません。このオブジェクトは pjs.load("root") を呼び出して取得します。load() 関数は Persistent JavaScript API が ID を基準にオブジェクトをロードするために定義している関数で、root はオブジェクト・データベースに含まれる root オブジェクトの別名 ID です。リスト 3 に、新しいブログ投稿を追加する関数を記載します。
リスト 3. addBlogPost() 関数
function addBlogPost() {
var blog = pjs.load("root").blog;
var newPost = {
title : "new post",
content : document.getElementById('newPostContent').value,
created : new Date(),
comments : [] // an empty array of comments
};
blog.push(newPost); // blog is an array, so we can add a new post to the top
// of the array using standard array functions
newPost.title = prompt("What would you like to title the new post?",newPost.title);
}
|
addBlogPost() が呼び出されると、新しい投稿がブログに追加されます。この操作全体は Persevere フレームワークによって自動的にトランザクションにラップされてからサーバーに送信され、永続化されます。直交永続性を使用している場合には、保存や永続化のためのメソッドを呼び出す必要はありません。プロパティーと配列の変更は自動的に保存されます。
次に作成するのはブログに投稿を表示するための関数です。コードをモジュール化するため、2 つの関数を作成する必要があります。1 つはブログ全体をレンダリングする関数、そしてもう 1 つは 1 本の投稿をレンダリングする関数です。これらの投稿を表示するためのJavaScript コードは、リスト 4 のとおりです。
リスト 4. ブログ用 HTML コードの作成
function renderBlog() {
var blog = pjs.load("root").blog; // get the blog object, the list of the postings
blogElement = document.getElementById("blogDiv");
blogElement.innerHTML = ""; // clear it out
for (var i =0; i < blog.length;i++) // iterate through blog posts, render each one
renderPost(blog[i],blogElement.appendChild(document.createElement('div')));
}
|
上記のように、単純な for ループを使ってブログに含まれる投稿を繰り返し処理します。Persevere は遅延ローディングを行って、必要なデータだけがダウンロードされるようにします。初期化されていないプロパティーにアクセスすると、Persevere は自動的にサーバーからの正しいデータを要求し、それから実行を再開します。Persevere は継続 (continuation) を使用して実行を中断、再開するため、非同期要求によってサーバーからデータが取得されます (したがって、同期要求が原因でブラウザーが動かなくなることはありません)。
ここで、各投稿をレンダリングするためのコードを入力します (リスト 5 を参照)。
リスト 5. 1本のブログを投稿するための HTML コードの作成
function renderPost(post,postDiv) {
var html = "<h2>" + post.title + "</h2>"
+ "<h4>" + post.created + "</h4><p>" + post.content + "</p>";
postDiv.innerHTML = html;
}
|
ページのロード時や addBlogPost を呼び出したときに新規投稿がすぐに表示されるようにするには、addBlogPost() 関数の終わりと blog.pjs の最後に renderBlog() の呼び出しを追加してください。さらに、push() メソッドの代わりに unshift() 配列メソッドを使用して、投稿をリストの終わりではなく先頭に追加することもできます。
新しいブログ・インターフェースを使用してブログに投稿を追加してみてください。ブログは正常に機能するはずです。投稿をいくつか追加すると、ブログは図 3 のようになります。
図 3. 新規ブログ
今度は永続オブジェクト・ブラウザーに戻って、保存されたデータを確認してください。図 4 のように、ブラウザーには投稿の履歴が表示されます。
図 4. 永続化されたブログ投稿のデータ
ブログ・エントリーにコメントする方法
ブログ投稿に関するコメントを投稿するための機能を追加することもできます。それには、ブログ投稿のクリック操作に応答して 1 本のブログ投稿をコメント付きで表示する onclick イベントを追加します。次に、1 本の投稿のビューにコメント・フォームを追加し、ブログ・オブジェクトに投稿を追加したときと同様の方法でブログ投稿にコメントを追加します。コメント機能を追加するためのコードは、「ダウンロード」セクションから入手することができます。また、Persevere がプロパティーを一時的なもの (つまり保存されないもの) として扱う場合と永続的なものとして扱う場合についての詳細は、Persevere の資料を参照してください。
Persevere の永続オブジェクトのマッピング機能と Persevere サーバーの動的オブジェクトの作成機能を使用することで、ブログに必要な永続性を容易に作成することができます。注目すべき点は、ブログを作成するために、データベース・テーブルを作成する必要も、Ajax 呼び出しや SQL (Structured Query Language) コードを作成する必要も、さらには構成ファイルを変更したり、コントローラーを作成したりする必要もなかったことです。単純明快な HTML および JavaScript コードを使ってブログを作成できました。
セキュリティー
作成したブログにはまだセキュリティーが施されていません。つまり、このブログには誰でも何の制約もなく投稿できるということです。たいていの Web アプリケーションでは、投稿のためのアクセスやその他の形でのデータの変更を制約する必要が出てきます。このブログのロジックはクライアント・サイドの JavaScript スクリプトに含まれていますが、セキュリティーが施されるのがクライアント上だけであってはなりません。
Persevere サーバーには、サーバー上で実行されるデータ中心のセキュリティー機能が組み込まれています。Web アプリケーションの開発シナリオのほとんどでは、便宜上、開発者はアプリケーション・ロジックにセキュリティーを実装することになります。しかしアプリケーション・ロジックが大きくなると、それだけ攻撃の危険性も大きくなるため、大規模な Web アプリケーションの場合、アプリケーション・ロジックにセキュリティーを実装するのは危険です。アプリケーション・ロジックが複雑になればなるほど、攻撃者が抜け穴を見つける可能性も高くなります。そこで、データ中心のセキュリティーを用いてアプリケーション・ロジックからセキュリティーを切り離せば、セキュリティーはより管理しやすくなるというわけです。
インストールしたばかりの Persevere サーバーは非セキュア・モードで起動します。セキュリティーを有効にするには、永続オブジェクト・ブラウザー (http://localhost:8080/browser.html) を開き、Sign in をクリックして新規ユーザーを作成してください。新規ユーザーが作成されるとセキュリティーが有効になり、そのユーザーがスーパー・ユーザーとして指定されます。セキュリティーが有効な場合、デフォルトのセキュリティー・レベルでは一般ユーザーが永続オブジェクトを読み取ることができますが、書き込みできるのはスーパー・ユーザー (新しく作成されたユーザー) だけです。永続オブジェクトごとにアクセス・レベルを指定する方法については、Persevere サーバーの資料 (「参考文献」を参照) で詳細を調べてください。
リレーショナル・データベース
永続オブジェクトのマッピング形式としてもっともよく使われているのは、おそらくオブジェクト・リレーショナル・マッピングでしょう。この記事ではクライアントが作成したデータ構造で永続オブジェクトをマッピングする方法について説明してきましたが、Persevere サーバーは Persevere での永続オブジェクトのマッピングとして、従来のリレーショナル・データベース、そして JSON REST サービスによる SQL データベース・テーブルのデータ公開をサポートしています。SQL データベース・テーブルの例を確認するには、永続オブジェクト・ブラウザーを開き、exampledatabasetable/ オブジェクトをロードしてください。load() 関数で JavaScript ファイルからこのデータをロードすると、通常の JavaScript 配列としてテーブルにアクセスできるようになります。このテーブルのデータは、リスト 6 の JavaScript コードを使って簡単に変更することができます。
リスト 6. JavaScript によるリレーショナル・データベースの操作
function changeNameForFirstRow() {
pjs.load("exampledatabasetable/")[0].name="New name";
}
|
上記のステートメントは、テーブルからデータをロードし、最初の行にある name 列の値を新しい値に変更します。サンプル・ブログで使用したオブジェクト・データベース・ストレージをリレーショナル・データベース・ストレージで置き換えることもできます。オブジェクトは抽象化されるため、リレーショナル・データベース・ストレージが正しく設定されていれば、ブログ・プロパティーを変更してリレーショナル・データベース・ストレージを参照させたとしてもブログ・アプリケーションはまったく同じように機能します。その際、コードの変更は一切必要ありません。
Persevere のその他の機能
Persevere には JSON Schema 定義のサポートが組み込まれています。JSON Schema が定義するのは、プロパティーの値に許容される型です。例えば、title プロパティーをストリングとして指定したり、コメント項目には author、created、および content プロパティーがなければならないことなどを指定したりできます。言わば、XML での DTD (Document Type Definition) やオブジェクト指向言語でのクラスのようなものです。また、構造でプロパティーが永続的なものか、あるいは一時的 (変更があっても保存されないということ) なものかを定義することもできます。Persevere がプロパティーを保持するときのルールを理解しておくことは重要なので、Persevere の資料 (「参考文献」を参照) をよく読んでください。
 |
Persevere を使ってクロスドメイン・データにアクセスする方法 Persevere は、さまざまなサーバーの永続化されたオブジェクト・グラフを含めることが可能なクロスドメインのオブジェクト・グラフの構築をサポートします。永続オブジェクト・ブラウザーで新規プロパティーを作成し、Existing by ID を選択してから JSON オブジェクトの URL を入力してください。 |
|
トランザクション
Persevere では変更を暗黙的にトランザクションにグループ化します。ある 1 つのイベントを処理する際に発生したすべての変更 (onclick イベントによって addBlogPost() で行われた変更など) はまとめて 1 つのトランザクションにグループ化されます。ブラウザーでのあらゆる JavaScript 処理はイベントのコンテキスト内で行われるため、この振る舞いはトランザクションを処理する上で都合が良く、ほとんどの場合で論理的な方法となります。
ただし、場合によってはトランザクションの追加制御が必要になることもあります。Persistent JavaScript API で定義しているトランザクションの制御用メソッドは pjs.commit() と pjs.rollback() の 2 つです。commit() メソッドは行われた変更の即時コミットを試行します。もう一方の rollback() メソッドは、イベントが開始されてから、あるいは最後にコミットされてから行われたすべての変更を取り消します。例えば addBlog() 関数の終わりに確認操作を追加し、この操作でキャンセルが選択された場合には、投稿が取り消されるようにすることができます (リスト 7 を参照)。
リスト 7. トランザクションの制御
function addBlogPost() {
...
if (!confirm("Are you sure you want to create this post?"))
pjs.rollback();
}
|
代替サーバー
Persevere JavaScript クライアントは Persevere サーバーに依存するわけではありません。サーバーとのすべての通信は標準 HTTP メソッドと JSON フォーマットに基づいて行われるため、Persevere を使って PHP や Ruby といった他の技術で永続オブジェクトをマッピングするのも難しい話ではありません。この記事では HTTP と JSPON の詳細は説明しませんが、サーバーに必要なのは、JSON を提供し、JSPON 仕様に従って標準 HTTP (PUT、POST、および DELETE) の変更要求を処理することだけです。
永続関数と分散コンピューティング
Persevere では関数またはメソッドの動的永続オブジェクトへの永続化をサポートします。このサンプル・ブログ・アプリケーションで作成したすべての関数は、ブログ永続オブジェクトのメソッドとして作成することもできます。また、この手法を使用すれば、アプリケーション・ロジック全体をデータと同じ永続ストレージに保存することも可能です。Persevere サーバーは内部 JavaScript 環境 (図 1 を参照) を使って永続オブジェクトをマッピングすることから、永続化された関数はクライアント上でだけではなくサーバー上でも同じように実行することができます。
Persevere サーバーは Persistent JavaScript (「参考文献」を参照) も実装しているので、関数はクライアント上での場合と同様に、サーバー上でも同じ永続データにアクセスすることができます。さらに JSON-RPC を使用することによって、通常の JavaScript 呼び出し構文を用いてリモート環境の関数を透過的に呼び出すこともできます。この機能は 1 つのストレージ媒体をロジックとデータの両方に使用するため、アプリケーションの環境に一層の一貫性をもたらすだけでなく、「ライブ感のある」リアルタイムのプログラミングも実現します。つまり、永続オブジェクト・ブラウザーでを使用して、その場で関数を作成し、テストして、保存することが可能になるということです。
 |
Ajax resource center developerWorks の Ajax resource center を詳細に調べてください。ここには無料のツール、コード、そして Ajax アプリケーションの開発を今すぐ始めるための情報が揃っています。活発に進められているディスカッション・フォーラムでは、今あなたが持っている疑問の答えが見つかるかもしれません。 |
|
まとめ
直交永続性を持つオブジェクト・マッピングを利用すれば、強力な Ajax アプリケーションを単純で馴染み深い JavaScript コードを使って難なく開発することができます。また、Persevere を使うことで Ajax リクエスト、シリアライズ、そしてデータベース操作を作成するという厄介な作業は簡単に処理することができるので、永続データへのオブジェクト指向によるアクセスが実現でき、迅速なアプリケーション開発が可能となります。
ダウンロード | 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|
| Example blog application1 | wa-aj-objmap.zip | 2KB | HTTP |
|---|
ご注意: - このブログは 49 行の JavaScript コードで作成されています。
参考文献 学ぶために
製品や技術を入手するために
議論するために
著者について  | 
|  | Kris Zyp はソフトウェア開発者、コンサルタント、そして Xucia の創立者であり、JavaScript の永続性とコルーチン、そしてその他の言語機能の分野を専門としています。彼は Persevere (JavaScript 永続オブジェクトのマッピング・フレームワーク)、Strands (JavaScript のコルーチンおよびスレッド化サポート)、Authenteo (Ajax ベースの Web コンテンツ管理システム)、JSPON 仕様を開発した他、JSPON ソースを使用するためのオープン・ソースのツールも開発しました。 |
記事の評価
|