XPagesでLotus Notes/Dominoアプリ開発入門
連載インデックスへ
XPagesでLotus Notes/Dominoアプリ開発入門(3)

サーバサイドJavaScriptでXPagesのロジック実装


日本アイ・ビー・エム株式会社 ソフトウェア開発研究所
Lotusテクノロジー開発 ソフトウェアエンジニア 小峯 宏秋
2012/8/8


XPagesアプリにおけるビジネスロジックの実装


今回の主な内容

 前回の「Javaサンプルの定番ショップカートをXPagesで作る」に引き続き、サンプルアプリを例にして、Lotus Notes/Dominoの新しい開発技術であるXPagesを紹介します。今回は、XPagesアプリにおけるビジネスロジックの実装について解説します。ショッピングカートアプリを例にXPagesの技術を説明します。

 前回で説明したように、アプリは以下の3つの機能から構成されています。この構成については前回の図2に概要図を掲載しています。

  1. 商品の一覧を示すカタログと商品の詳細を表示する機能
  2. 購入予定の商品を一時的に保持し、ショッピングカートで表示する機能
  3. 購入者の情報や支払い情報を入力し、ショッピングを完了する機能

 このうち1については、すでに前回で解説しました。今回は2と3について詳しく見てみましょう。

 2は、ユーザーが選択した商品をショッピングカートのデータとして保持しておく仕組みです。このデータは商品の購入が確定するまでは未確定のデータであり、Webブラウザのセッションに関連付けてサーバのメモリ上に保持します。

 3では、ユーザーに住所や氏名などの顧客情報を入力させ、購入する商品の情報とともにLotus Notes/Dominoアプリに永続的なデータとして保存する仕組みを用意します。

 ここで紹介するサンプルアプリは、XPages.infoの日本語アプリのデモページで、「IBM製日本語 XPagesアプリライブデモ」セクションにある「ショッピングカートアプリ」として公開しています。ぜひお試しください。

JavaScriptを書かずともロジックが書ける

 XPagesアプリでは、ページやページ内に配置したボタンなどのコントロールで発生するイベントに関連してさまざまなビジネスロジックを実装できます。そのロジックの実行場所は、クライアントサイドとサーバサイドが選択できます。

 クライアントサイドの処理では、XPagesによって生成されるHTMLにJavaScriptとしてロジックが埋め込まれ、クライアントのWebブラウザが搭載しているJavaScriptのインタプリタで実行されます。一方サーバサイドJavaScriptはLotus Dominoに搭載されているインタプリタで実行されます。

 クライアントサイドとサーバサイドの両方で、処理内容をJavaScriptで記述できますが、よく使われる機能についてはシンプルアクションとして設定画面の選択肢から選ぶこともできます(図1)。シンプルアクションを使うとJavaScriptのコーディングが必要なく、プログラミングのスキルなしでアプリのビジネスロジックを実装できます。

図1 ボタンのイベントとしてサーバサイドのシンプルアクションの設定

 サーバサイドのシンプルアクションでは、ページの遷移や入力フィールドへの値の設定、データソースとして指定されているLotus Notes/Dominoアプリのデータの更新や削除といった、アプリ開発に必要な基本的な機能が提供されており、シンプルアクションだけである程度のビジネスロジックが実装できます。

 そして、シンプルアクションでは実装できないような処理であれば、スクリプトエディタを選択してJavaScriptでロジックを実装できます(図2)。

図2 XPagesでのイベント処理の実装方法

サーバサイドJavaScriptの特徴

 前回紹介したように、Lotus Domino上で実行されるサーバサイドJavaScriptはECMA 262(ECMAScript)に準拠しながら、XPagesアプリで使用するための以下の拡張がなされています。

  • Lotus Notes/Dominoアプリへのデータアクセス
  • ブラウザコンテキスト情報などを保持するグローバル変数へのアクセス
  • セッション情報などを保持するスコープ変数へのアクセス
  • Javaクラスへのアクセス

 XPagesアプリ開発では、基本的な処理はシンプルアクションで実装でき、複雑な処理であればサーバサイドJavaScriptでの実装が可能です。JavaScriptだけでは実装しにくい複雑な処理などはJavaで実装し、そのクラスをJavaScriptから呼び出すことも可能です。

 本記事で紹介するショッピングカートアプリでは、これらのサーバサイドJavaScriptの拡張機能を随所で使用しています。例えば、ユーザーがショッピングカートに入れた商品の情報はセッション範囲のスコープ変数で保持し、確定した購入商品情報や顧客情報はLotus Notes/Dominoアプリへのデータアクセスで保存しています。

 またクレジットカード決済では、クレジットカード番号の検証を行うJavaクラスを呼び出しています。

ショッピングカートの実装

 ショッピングカートアプリの3つの機能のうちの2番目、「購入予定の商品を一時的に保持し、ショッピングカートで表示する機能」の実装を見てみましょう。

 ショッピングカートアプリでは、商品詳細画面で購入点数を選択し「ショッピングカートに入れる」ボタンを押すと、商品がショッピングカートに追加されます(図3)。

図3 商品詳細画面と「ショッピングカートに入れる」ボタン

 このときショッピングカートの中の商品はまだ購入を確定していません。顧客がこのWebサイトにアクセスしている間だけ一時的に保持されていれば十分なデータです。ショッピングカートアプリでは、この処理はサーバサイドJavaScriptで実装され、ショッピングカートの商品情報はメモリ上でWebブラウザのセッションに関連付けたデータとして保持されています。ユーザーは選択した商品の中身をショッピングカートで確認できます。

 商品詳細画面を表示するページは、前回の記事で「フォーム」をデータソースとして作成したXPageです。商品の詳細なデータを表示したり、購入点数を選択したりするために以下のようなコントロールが配置されています。

商品詳細画面の表示・設定項目 XPagesコントロールのID
商品番号 productID
商品名 productName
商品価格 productPrice
購入点数 orderCount

 「カートへ追加」ボタンが押されたときに商品がショッピングカートへ追加されるよう、ボタンの「onClick」イベントの処理スクリプトにリスト1のようなJavaScriptを実装します。ここで行っている処理は次のようになります。

  リスト1 「カートへ追加」ボタンの「onClick」イベント処理
var noteId = currentDocument.getNoteID();
var productId = getComponent("productID").value;
var productName = getComponent("productName").value;
var productPrice = Number(getComponent("productPrice").value);
var orderCount = Number(getComponent("orderCount").value);
 
updateOrder(noteId, productId, productName, productPrice, orderCount);
  1. 表示中の商品の詳細情報を保持している「文書」を参照できるように文書IDを取得。これは「currentDocument」グローバル変数の「getNoteID()」関数を使用している
  2. 表示している画面から商品の情報や購入点数のデータを「getComponent()」グローバル関数で取得
  3. 取得したデータを基にショッピングカートへ商品を追加する関数updateOrder()を呼び出す。この関数はスクリプトライブラリに定義している

 スクリプトライブラリに定義されている「updateOrder()」関数の内容をリスト2に示しています。ここでは、セッション範囲のスコープ変数である「sessionScope」変数のプロパティとして「cart」が存在するかを確認し、なければ配列でlist変数を新たに定義しています。すでに配列に商品があるかどうかと指定された購入点数に応じて、実際の処理を行うそれぞれの関数を呼び出しています。

  リスト2 スクリプトライブラリでの購入商品の更新をする「updateOrder()」関数
/*
 * ショッピングカートのオーダーを更新
 * _noteID	カタログ文書の Note ID
 * _prodId	商品番号
 * _prodName	商品名
 * _prodPrice	価格
 * _orderCount	購入点数
 */
function updateOrder(_noteId, _prodId, _prodName, _prodPrice, _orderCount) {
 
    /*
     * セッション範囲のスコープ変数からカートデータを取得、なければ生成
     */
    var list = new Array();
    if (sessionScope.cart) {
        list = sessionScope.cart;
    } else {
        list = new Array();
    }
    
    /*
     * アップデートする商品があるかを確認し、なければ追加、あれば更新
     * 購入点数が 0 なら、オーダーから削除
     */
    var index = findOrder(list, _prodId);
    if ((-1 == index) && (0 != _orderCount)) {
        list = addOrder(list, _noteId,
                 _prodId, _prodName, _prodPrice, _orderCount);
    } else {
        if (0 == _orderCount) {
            list = removeOrder(list, index);
        } else {
            list = replaceOrder(list, index, _noteId,
                 _prodId, _prodName, _prodPrice, _orderCount);
        }
    }
    
    /*
     * 更新されたカートのデータをスコープ変数に保存
     */
    sessionScope.cart = list;
}

 新しい商品を購入するときには「addOrder()」関数を呼びます。この関数もスクリプトライブラリに定義されており、追加された商品の購入情報を配列に追加して返します。呼び出し元の「updateOrder()」関数では更新された配列を「sessionScope」変数の「cart」プロパティに設定して値を保持しています(リスト3)。

  リスト3 追加された商品の購入情報を配列に追加する「addOrder()」関数
/*
 * プライベート関数:ショッピングカートにオーダーを追加
 */
function addOrder(_list, _noteId, _prodId, _prodName, _prodPrice, _orderCount) {
    var entry = new Object();
    entry.noteId = _noteId;
    entry.productId = _prodId;
    entry.productName = _prodName;
    entry.productPrice = _prodPrice;
    entry.orderCount = _orderCount;
 
    _list.push(entry);
 
    return _list;
}

 次にショッピングカートの中身を表示するショッピングカート画面を見てみましょう。表示するショッピングカートの商品一覧はセッション範囲のスコープ変数の「cart」プロパティに配列のデータとして入っており、スクリプトライブラリの 「getAllOrder()」 関数で取得できます(リスト4)。

  リスト4 ショッピングカートの商品一覧を返す「getAllOrder()」関数
/*
 * ショッピングカートから一覧を取得
 */
function getAllOrder() {
    return sessionScope.cart;
}

 配列として取得された商品のデータは、XPagesの繰り返しコントロールと呼ばれるコントロールで表示します。図4のように繰り返しコントロールの設定で、「getAllOrder()」関数から戻される配列を「使用するバインドデータ」に設定しています。

図4 繰り返しコントロールのプロパティ

 繰り返しコントロールの中では、配列の要素の数だけ同じ画面要素を繰り返し生成し、その画面要素の中では配列内の個々のデータに、「コレクション名」で定義した「orderEntry」変数でアクセスできます。例えば、商品名を表示するには繰り返しコントロールに計算結果コントロールを配置し、その値にリスト5のようなスクリプトを記述します。

  リスト5 商品名を出力する計算結果コントロールの値
return orderEntry.productName;

 繰り返しコントロールの中で商品番号、商品名、価格、購入点数を表示するようにして完成したショッピングカートの画面は図5のようになります。

図5 ショッピングカートの画面

1-2

 Index
第3回 サーバサイドJavaScriptでXPagesのロジック実装
Page1
XPagesアプリにおけるビジネスロジックの実装
JavaScriptを書かずともロジックが書ける
サーバサイドJavaScriptの特徴
ショッピングカートの実装
Page2
レジ画面の実装
Java EE開発者もLotus Notes/Domino開発者も


Java Solution全記事一覧



Java Agile フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Java Agile 記事ランキング

本日 月間