RequestDispatcherとServletContextを活用した、より具体的なサンプル

 

 


 


RequestDispatcherServletContextを活用した、より具体的なサンプル

 

あるレストランがあったとする。ウェイトレス(RestaurantWaitress)が顧客に本日のメニューを示し、顧客から注文を受ける。顧客が本日の仕込数以上を注文したり品切れになっていたら、ウェイトレスでは荷が重いので店長(RestaurantMaster)に丁寧にお断りしてもらう。メニューにあれば、それをシェフ(RestaurantChef)に伝え、シェフが作った料理を顧客に渡す。メニューは毎朝シェフが作成し、店長がそれに価格を付加する。

 

このシナリオでは、顧客、ウェイトレス、店長、シェフ、メニューの5つのオブジェクトが存在する。顧客は皆さんでありHTTPブラウザである。ウェイトレス、シェフ、店長の3人はサーブレットで構成しよう。メニューは4者が共有するものなので、コンテキストの属性のひとつとして扱おう。

 


 

 


そうすると、このアプリケーションの構成は次のようになる。ウェイトレスは顧客の注文を受けるので、URLパタンは/RestaurantCresc/Dinnerとしよう。顧客の注文は通常はChefに転送され、RestaurantChefは注文された料理を調理する。顧客が指定した料理が本日の仕込数を超えてしまったときはその注文をRestaurantMasterに転送し、RestaurantMasterがその顧客に丁寧にお断りする。RestaurantChefは毎朝本日のメニューを作成し、RestaurantMasterが価格を記入するが、それは各々のサーブレットをHTTPで呼び出して行うことにする。その場合、複数のスレッドは到来しないものとする。顧客にはもちろん複数のスレッドとして対応する。

 

ソフトウエアのポイントはRestaurantMenuをこのコンテキストの属性として3つのサーブレットが共有すること、RestaurantWaitressが顧客からの要求をCookRestaurantMasterに転送(Dispatch)することである。これらはContextインターフェイスのメソッドを利用している。そうするとRestaurantChefRestaurantMasterへは要求が2箇所から来ることになるので、ServletRequestの属性に(“sender”, “waitress”)という名前と値のペアが存在すればこれはRestaurantWaitressが転送してきたものだと判断するようにする。

 

さらに注意しなければならない事項として、RestaurantMenuの共有問題がある。シェフやマスターがメニューをいじっているときには、そのメニューは顧客には示せない。値段やできる料理や仕込数が変更される危険性があるからである。メニューがビジーの場合は他の人は待たねばならないとする。

 

プレイヤー

ビジーの期間

RestaurantChef

本日のメニューを作成中

RestaurantMaster

メニューに価格を設定中

RestaurantWaitress

顧客に示して顧客が注文をおわるまで

 

Webアプリケーションの場合は、この様な排他制御にクライアントの異常終了に十分注意する必要がある。つまりクライアントは、選択画面をあけたまま長時間放置したり、ブラウザを終了させてしまう危険性がある。この場合、そのクライアントにメニューをロックされたままになり、そのレストランは営業が出来なくなってしまう。ある顧客がウェイトレスからメニューを受け取ったままその店を飛び出てしまったら、他の顧客は食事にありつけない。

 

皆さんがそこのマスターになった気持ちになれば、いろいろな対策が考えられよう。例えば:

-     ビジーである旨をクライアントに返し、再度アクセスしてもらう。

-     マスターが責任をもち、マスターが強制的にメニューをとりもどす。

-     セッションのタイムアウトでメニューを開放する。

-     ある時間以上メニューがビジーで待たされたら、その人が強制的にメニューを取得する。

-     一定時間以上メニューがビジーとなったら(ビジーフラグのタイムアウト)そのメニューを開放する。

-     などなど....

どういう手を打つかはアプリケーションの設計の問題である。一般的にはビジーのときは即ビジーであるむねをクライアントに返したほうが問題を生じにくい。ここでは2番目の対策だけを採用しよう。つまり、RestaurantMasterをブラウザからアクセスしたときは、強制的にビジーはマスターが取得する。その際待機中のスレッドがあったら、それを全て開放する。RestaurantMasterとのセッションが終了するとメニューは開放され、他のプレイヤーたちが利用できるようになる。

 

RestaurantMenuと同様コンテキストの属性となっているRestaurantMenuBusyFlagはその為のフラグであるが、これはスレッドのところで紹介したBusyFlagクラスとは、ビジーを取得したスレッドとそれを開放するスレッドは同じでないという点で少々異なる。メニューを取得したスレッドは、サーブレットを終了しHTTP応答を送信したら削除されるかまたはスレッドのプールに戻される。これはサーブレット・エンジンの実装の問題である。メニューを開放するのは一般に次のHTTP要求のスレッドである。これは一般には前回のHTTP要求のスレッドとは異なる。従ってBusyFlagクラスのbusyflagというクラス変数はThreadクラス型オブジェクトであったが、これを使うと参照されるスレッドが存在しなくなっている可能性がある。従って今回はThread.toString()メソッドを使ってString型のオブジェクトとする。

 

さて実際の動作をスクリーン画面で説明しよう。

 


 


右からRestaurantWaitressRestaurantChefRestaurantMasterをアクセスして各々セッションを終了した状態である。RestaurantWaitressは顧客から受けた注文をシェフにまわし、シェフが作った料理を顧客に運び、最後に会計を請求している。左の画面のRestaurantChefは本日のメニューのアイテムを選択し、各アイテムの仕込数を設定した画面である。中央のRestaurantMaster画面は、マスターがメニューの各アイテムに単価を設定し終わった状態である。

 

 

前節     目次     次節