 |
ソフトウェア > Lotus > Lotus Developer Domain >
Iris Today Archives
ドミノでのサーブレットの開発
 |
 |
 |
by Anthony Patton
レベル:上級者
対 象:Domino 5.0
原文の掲載:2001年2月1日
ドミノ R5 では、Java サーブレットをサポートしており、アプリケーションの開発の際の選択の幅が広がりました。たとえば、ドミノ・エージェントの代わりにサーブレットを用いてドミノ・オブジェクトにアクセスしたり、サーブレットでサーバーでの処理を行うことができます。
この記事では、エージェントとサーブレットの相違点やサーブレットを使用するためのサーバーの設定、基本的なサーブレットの構造といった、サーブレットの基本的な内容についての紹介をします。そして、3つのサーブレットの例について詳細に説明をします。
この記事では、JavaScript になじみがあり、ドミノ・アプリケーションの設計について理解していることを前提にしています。
サーブレットとは、サーバー上で実行される Java のプログラムのことで、CGI
(Common Gateway Interface) アプリケーションや、ドミノ・エージェントと同様の機能を提供するものです。サーブレットの主な利点は、メモリー上に一回だけ読み込めば良いということです。これに対して、ドミノ・エージェントや
CGI プログラムは、呼び出されるたびにメモリーに読み込まれます。一度読み込まれると、サーブレットに対するすべての呼び出しで、同一のインスタンスが用いられます。
ドミノ・エージェントやサーブレットは、同様の機能を提供しますが、実装の点では大きく異なります。エージェントがドミノ・データベース内に存在するのに対して、サーブレットは、ファイル・システム上に存在します。この違いによって、配布とセキュリティーの2点について注意すべき点があります。
ドミノ・エージェントは、データベース内に存在するという点に大きな利点があります。複製を用いて他のドミノ
サーバーに配布されます。さらに、ドミノのセキュリティー・モデルによりエージェントのアクセス権が決定します。
逆に、サーブレットはファイル・システム上に存在するため、サーバーやファイル、ディレクトリーのセキュリティー機構によりアクセス権を制御します。デフォルトでは、サーブレットはサーバーのセキュリティー権限で実行されます。しかし、特定のユーザー
ID とパスワードが必要となります。最後に、Windows NT 上でディレクトリーの複製を使用しない場合は、使用したいすべてのシステム上にサーブレット・ファイルをコピーするかインストールする必要があります。
標準的なドミノデザイナーの開発環境ではサーブレットの開発をサポートしていないので、サーブレットのコードの開発をするには、サード・パーティー製の開発環境や、サンのコマンド・ライン
JDK を使用しなければなりません。(IBM の VisualAge for Java を用いた開発については、Iris
Today の記事「VisualAge for Java を使ってドミノにサーブレットを作成する」をご覧ください。)
サーブレットを開発するために必要なクラスとして、サン・マイクロシステムズ社からJSDK (Java Servlet Development Kit) が無料で提供されています。さらに、JSDK
はドミノに標準でインストールされています。JSDK.JAR ファイルがドミノをインストールしたディレクトリーに置かれます。たとえば、私のドミノ
サーバーは D ドライブの r5server というディレクトリーにインストールされているので、そのファイルのパスは次のようになります。
D:\r5server\jsdk.jar
メモ:Jar ファイルは Java ファイルを圧縮するための標準形式です。これは、WinZip
や PKZip、Windows の CAB ファイルと同様のものです。 |
|
|
| |
 |
ドミノ R5 には独自のサーブレット・マネージャーがありますが、IBM の WebSphere
といった、サード・パーティーのサーブレット・エンジンを使用することもできます。(現在では、WebSphere
は、ドミノでサポートしている唯一のサーブレット・エンジンです。)ドミノ・ディレクトリー内にあるサーバーの文書にはサーブレットの設定に関するセクションがあります。これらの設定は、[インターネットプロトコル]
- [Domino Web Engine] タブの Java サーブレットの部分にあります。以下の例は、私のテスト・サーバーでのサーブレットの設定です。

オプションについての解説
| オプション |
説明 |
| Java サーブレット・サポート |
これによりサーブレットを使用の有無を設定します。[なし]、[Domino Servlet
Manager]、[サードパーティーのサーブレットサポート] の中から値を選択します。 |
| サーブレット URL パス |
これは、サーブレットにアクセスするために使用する URL のことです。適切に実行するために必要となるサーブレット関連のファイルがあるディレクトリーです。 |
| クラス・パス |
実行したいサーブレットを置く場所で、ローカルのディレクトリーを指定します。ドミノのサーブレット・マネージャーは、サーブレットをクラス・パスで指定されたディレクトリーに置きます。 |
| サーブレット・ファイル拡張子 |
ドミノがサーブレットを参照する際に、必要となる URL ファイルの拡張子。コンマで区切ることで複数の拡張子を指定できます。 |
| セッション状態トラッキング |
この設定を有効または無効にすることで、サーブレット・マネージャーはアイドル状態のセッションを終了させるかどうかを選択できます。アイドル状態のセッションの時間制限は次のフィールドで設定されます。 |
| アイドル状態のセッションのタイムアウト |
接続が終了するまでのまでの待機時間(分)です。これは、セッション状態のトラッキングが有効な場合のみ適用されます。デフォルトは
30 分です。 |
| 最大セッション数 |
同時に使用可能なアクティブなサーブレットのセッションの数。デフォルトは
1000 セッションです。 |
| セッションの保持 |
この設定を有効または無効にすることで、セッションの情報をディスクに保存するかどうかを選択できます。 |
ドミノ・サーブレットは、Java 仮想マシン (JVM: Java Virtual Machine) とサーブレット・マネージャーの2つの部分に分けることができます。サーブレットが有効な場合、Java
仮想マシンは、HTTP サーバーが開始する前にロードされます。結果として、ドミノのサーブレット・マネージャーが使用される場合は、HTTP
サーバーは Java 仮想マシンがロードされた後にロードされます。サード・パーティー製のサーブレット・マネージャーを使用する場合は、Java
仮想マシンがロードされるだけです。
ドミノのサーブレット・エンジンは、サーブレットをロードしたときに標準的なパラメーターを指定するための設定ファイルをサポートしています。これは、servlets.properties
という名前のファイルで、ドミノをインストールしたデータ・ディレクトリーに置かれます。たとえば、以下のようになります。
D:\r5server\data\servlets.properties
もしファイルを見つけられない場合、Windows のノート・パッドなどのテキスト・エディターを用いて簡単に作成できます。
サーブレットのプロパティー・ファイルで、別名や初期化引数、URL 拡張子マッピング、Web
サーバーのスタートアップ時にサーブレットのロードを行うなどの設定ができます。また、コメントを挿入することもできます。
サーブレットの別名
alias 文は以下のような構文になります。
servlet.<alias-name>.code=<class-name>
初期化引数
プロパティー・ファイルで、サーブレットの初期化データを指定できます。サーブレットは
ServletConfig.getInitParameter メソッドを用いてデータにアクセスできます。初期化の構文は以下のようになります。
servlet.<alias or class name>.initArgs=<name1=value1>,<name2=value2>
URL 拡張子マッピング
URL 拡張子マッピングの構文は以下のようになります。
servlet.<alias or class name>.extension=<extension> <extension>
...
起動時にロード
スタートアップの構文は以下のようになります。
servlets.startup=<alias or class> <alias or class> ...
以下に、HelloWorld.class (拡張子の .class はあっても無くても構いません)
サーブレットに名前 (Test) を割り当てている servlets.properties ファイルを示します。初期化引数が割り当てられ、起動時にロードされます。
# Example servlets.properties file
servlet.Test.code = HelloWorld
servlet.Test.initArgs = 1, 2, 3
servlets.startup = Test
サーブレットを Web サーバーの起動時にロードすることで、その時点からメモリー上で利用できます。しかしながら、次のことに注意してください。サーブレットのコードに変更を加えた場合、ドミノ
HTTP サーバーをシャットダウンし、再起動しなければ、その変更は反映されません。再起動のコマンドは次の通りです。
Tell HTTP restart
一般的な誤り
サーブレットの設定ファイルに関する一般的な誤りを以下に列挙します。
- ファイルを誤ったディレクトリーに置く。ファイルはドミノのデータ・ディレクトリーに配置しなければなりません。
- 誤った拡張子を使用する。ノート・パッドのような多くのエディターは、勝手に
.TXT 拡張子をファイルに付けることがあります。
- 間違ったファイル名を使用している。ファイル名はservlets.properties でなければなりません。
- 大文字小文字の違いを無視している。ファイル名やサーブレットの名前と割り当てステートメントの大文字小文字は区別されます。
ドミノ サーバーでサーブレットを有効にすると、サーブレットに関する行がドミノの設定ファイル
(domino.cnf) に追加されます。このファイルは、データ・ディレクトリーに配置され、以下のような行が含まれるはずです。
# Java Servlet Settings
ServerInit servlet:ServletInit d:\r5server\Data
Service /servlet/* servlet:ServletService*
ServerTerm servlet:ServletTerm
先ほど述べたように、サーブレットは一度だけメモリー上にロードされます。ロードされると、init
メソッドが実行されます。service メソッドはクライアントがサーブレットにリクエストを出すたびに実行され、クライアントのリクエストに応じて
doPost や doGet メソッドが呼び出されます。
サーブレットは、次の2通りの方法でロードできます。サーブレット・マネージャーは、HTTP
サーバーの起動時にservlets.properties ファイルの指定に従うか、クライアントから初期化の要求が来たときにロードします。そして
HTTP のタスクをシャットダウンするときにサーブレットは廃棄 (メモリーから消去)
されます。
できるかぎり serlvets.properties ファイルを通じてサーブレット・マネージャーを使用してください。これは、HTTP
サーバーの起動時にロードすることで、クライアントのリクエストを滞りなく処理でき、サーブレットの最初と最近のリクエストでほぼ等しい応答時間を提供できます。
HTTP リクエストは、get と post の2種類に分けることができます。get メソッドは
URL の後ろに情報を付け加え、環境変数 query_string から利用します。post
は、名前と値をペアにして情報を送ります。
サーブレットの開発には、JSDK から、javax.servlet と javax.servlet.http
の2つのパッケージが提供されており、post や get メソッドと共に機能します。これらのパッケージは
Java サーブレットにインポートされます。
理解しておくべき重要な3つのメソッドを以下に挙げます。
- service
このメソッドはサーバーがサーブレットにリクエストを発行するたびに呼び出されます。通常、このメソッドは
HTTP サーブレットでは使用されません。これは一般的なサービスに適しています。
- doPostWeb
サーバーからサーブレットに発行されるすべての post リクエストはこのメソッドを起動します。フォーマットは以下のようになります。
public void doPost(HttpServletRequest req, HttpServletResponse res)
- doGet
Web サーバーからサーブレットに発行されるすべての get リクエストはこのメソッドを起動します。フォーマットは以下のようになります。
public void doGet(HttpServletRequest req, HttpServletResponse res
最も頻繁に使用する2つのメソッドは、doPost と doGet です。各メソッドは、HttpServletRequest
と HttpServletResponse の2つのパラメーターを取ります。
HttpServletRequest
HttpServletRequest オブジェクトには、クライアントからのリクエストに関するすべての情報が含まれています。このオブジェクトはリクエスト・ヘッダーや
CGI 変数、クッキー、フォーム・データにアクセスしたり、セッションの追跡を行うために使用されます。実際には、到着したフォーム・データを調べて、サーブレットのパラメーターに格納します。
HttpServletRequest クラスのメソッド
| メソッド |
説明 |
| getContentLength |
コンテント長をバイト単位で返します。 |
| getContentType |
コンテントの MIME タイプを返します。 |
| getCookies |
クッキー・オブジェクトの配列を返します。 |
| getMethod |
利用している HTTP メソッドを返します。 |
| getParameter(String name) |
指定したパラメーターの値を返します。サーブレット・エンジンはすべての HTML
フォームの値をパラメーターに配置します。このメソッドは単一値のパラメーターで利用します。 |
| getParameterValue(String name) |
接続が終了するまでのまでの待機時間(分)です。これは、セッション状態のトラッキングが有効な場合のみ適用されます。デフォルトは
30 分です。 |
| getQueryString |
リクエスト元の URL から Query string を返します。 |
| getRemoteUser |
(もしあれば) リクエストしたユーザーの名前を返します。 |
HttpServletResponse
HttpServletResponse オブジェクトは、サーブレットからクライアントなどのリクエスト元への通信のために使用されます。メソッドの一部を以下に示します。
HttpServletResponseクラスのメソッド
| メソッド |
説明 |
| getWriter |
応答データをリクエスト元に送るための PrintWriter オブジェクトを返します。 |
| sendRedirect(String url) |
指定した URL に応答をリダイレクトします。 |
| setContentType(String type) |
リクエスト元に送るコンテントのタイプを設定します。 |
| setStatus(int code) |
HTTP の状態コードを設定します。 |
ここで、簡単なサーブレットの例を取り上げます。最初の4行は必要な情報を取りこむためのものです。最初に出力をリクエスト元のクライアントに送るための
Java のクラスを取り込み、2番目に、入出力エラーを扱うための Java クラスを取り込んでいます。3、4番目は
Java サーブレットのクラスを取り込んでいます。
import java.io.PrintWriter;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
次に、サーブレット・クラスと doGet メソッドの宣言です。
public class Example_1 extends HttpServlet
{
public void doGet(HttpServletRequest req,HttpServletResponse res)
throws ServletException,IOException
{
クライアントとしてブラウザーを想定しているため、次に出力のコンテント・タイプとしてHTML
を指定します。そしてコンテンツをブラウザーに送るための PrintWriter オブジェクトを初期化します。
res.setContentType(“text/html”);
PrintWriter toBrowser = res.getWriter();
次の部分では、ブラウザーに HTML を送ります。
toBrowser.println(“<HTML”);
toBrowser.println(“<HEAD>");
toBrowser.println("<TITLE>Example Servlet</TITLE>");
toBrowser.println("</HEAD>”);
toBrowser.println(“<BODY>”);
toBrowser.println(“<H1>Servlet Example</H1>”);
toBrowser.println(“<BR><HR><BR>”);
toBrowser.print(“<H2>This was generated by the servlet”);
toBrowser.println(“doGet method on a Domino server.</H2>”);
toBrowser.println(“</BODY></HTML>”);
}
最後に、doPost メソッドで処理が完了します。
public void doPost(HttpServletRequest req,
HttpServletResponseres)
throws ServletException, IOException
{
res.setContentType(“text/html”);
PrintWriter toBrowser = res.getWriter();
toBrowser.println(“<HTML”);
toBrowser.println(“<HEAD>");
toBrowser.print(“<TITLE>Example - Servlet</TITLE></HEAD>”);
toBrowser.println(“</HEAD>");
toBrowser.println(“<BODY>”);
toBrowser.println(“<H1>Servlet Example</H1>”);
toBrowser.println(“<BR><HR><BR>”);
toBrowser.print(“<H2>This was generated by the servlet”);
toBrowser.println(“doPost method on a Domino server.</H2>”);
toBrowser.println(“</BODY></HTML>”);
}
}
以下に Internet Explorer からサーブレットを呼び出した結果を示します。

そして、サーブレットが呼び出されたときにドミノ サーバーで起こったことを示します。クライアントのリクエストがサーバーに送られたときに
Java サーブレット・マネージャーがロードされたことに注目してください。

最後の行の "Addin: Agent printing: Example_1: init" は、サーブレットがサーバーのメモリー上にロードされたことを表しています。それ以降の各呼び出しでこのインスタンスが利用されます。これは、サーブレットに繰り返しリクエストを出すことで確認することができます。(ブラウザーをシャットダウンして再起動しても構いません)
サーブレットを変更する
サーブレットを変更する手続きは重要な点です。サーブレットのコードを変更して再コンパイルすれば、ドミノ
サーバーはサーブレットをリロードしなければなりません。これは自動的に実行されるのではなく、HTTP
タスクを再起動しなければなりません。以下の画面は HTTP サーバーを再起動した場面を示しています。サーブレットが破壊され、クライアントからのリクエストが到着するとリロードされる点に注目してください。

サーバーの起動時にサーブレットをロードする
別の状況として、サーバーの起動時にサーブレットをロードするということができます。servlets.properties
ファイルを変更して、ドミノ サーバーの起動時にサーブレットをロードすることができます。たとえば、名前が
NotesNetTest であれば、プロパティー・ファイルは以下のようになるでしょう。
servlet.NotesNetTest.code = Example_1
servlets.startup = NotesNetTest
下の画面は起動時のドミノ サーバーのコンソールです。HTTP サーバーのタスクの前にサーブレットがロードされていることに注目してください。

これで、NotesNetTest という名前を用いてサーブレットを呼び出すことができ、以下に示すような結果が得られます。
サーブレットとドミノを緊密に統合することに焦点を当てましょう。次の例は、サーブレット中でドミノ・オブジェクトを用いており、ドミノ・ディレクトリーのエントリーにアクセスしています。
はじめに、プログラム・コードは先ほどの例と似通っていますが、lotus.domino.*
で必要なドミノの Java クラスを取り込んでいる点が異なります。
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import lotus.domino.*;
public class Example_2 extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException{
res.setContentType("text/html");
PrintWriter toBrowser = res.getWriter();
toBrowser.println("<HTML");
toBrowser.println("<HEAD>");
toBrowser.println("<TITLE>Example 2</TITLE>");
toBrowser.println("</HEAD>");
toBrowser.println("<BODY>");
toBrowser.println("<H1>Example 2</H1>");
ドミノ・オブジェクトの呼び出しは、try/catch ブロックで囲まれていなければなりません。そのため、次の行には
try{ があります。このブロック内では、ドミノ・オブジェクトにアクセスするために
NotesThread オブジェクトを作成しています。そして、新しく Session オブジェクトを作成します。Session
オブジェクトにパラメーターを与えていないため、サーバーからアクセスされることになりますが、代わりに、ユーザーの名前やパスワードを指定します。次に、ドミノ・ディレクトリー
(names.nsf) と People ビューにアクセスし、ビューの最初のドキュメントを呼び出します。
try {
NotesThread.sinitThread();
Session s = NotesFactory.createSession();
Database db = s.getDatabase("","names.nsf");
View vw = db.getView("People");
Document doc = vw.getFirstDocument();
toBrowser.println(db.getTitle());
toBrowser.println("<TABLE>");
while (doc != null)
{
toBrowser.println("<TR><TD>");
toBrowser.println(doc.getItemValueString("LastName"));
toBrowser.println("</TD></TR>");
doc = vw.getNextDocument(doc);
}
toBrowser.println("</TABLE>");
vw.recycle();
db.recycle();
s.recycle();
}
catch (NotesException n) {
toBrowser の行では、データベースの名前をリクエスト元のクライアント (ブラウザー)
に送信しています。while(doc!=null) は、ビューのすべての文書を調べるためのループで、ブラウザー内での各文書の
LastName の値を表示し、ビューの次の文書を取得しています。最後の文書が終わると、ドミノ・オブジェクトで使用されていたメモリー領域をシステムに解放します。
最後に、発生したエラーを表示し、finally ブロックでは NotesThread オブジェクトを終了させます。
System.out.println("Exception ID: " + n.id);
System.out.println("Exception description: " + n.text);
}
finally
{
NotesThread.stermThread(); }
toBrowser.println("</BODY></HTML>");
}
}
下の画面では、テスト・サーバー上のサーブレットにアクセスした結果を示しています。
これまでにサーブレットの構築方法や、ドミノ・オブジェクトの組み込み方を見てきましたが、次はサーブレットとドミノ・フォームの結合について焦点を当てましょう。まずプログラム・コードを検討し、フォームを組み立てましょう。
以下のプログラム・コードはフォームから提出された値を扱うサーブレットです。値はフォームから取得し、ドミノ・データベース内の新しいエントリーを格納するために使用されます。プログラムはクラスやパッケージの取り込みという標準的な行から始まります。そして、フォームの
FName や LName、Email、Phone フィールドから値を取得します。
import javax.servlet.*;
import javax.servlet.http.*;
import lotus.domino.*;
import java.io.PrintWriter;
import java.io.IOException;
public class Example_3 extends HttpServlet
{
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{
res.setContentType("text/html");
PrintWriter pw = res.getWriter();
pw.println("<html>");
pw.println("<head>");
pw.println("<title>Example 3</title>");
pw.println("</head>");
pw.println("<body>");
pw.println("<h1>Thank you!</h1>");
String fname = req.getParameter("FName");
String lname = req.getParameter("LName");
String email = req.getParameter("Email");
String phone = req.getParameter("Phone");
次に、先ほどのサーブレットで行ったように、NotesThread オブジェクトを作成し、ドミノ・オブジェクトと協調させるために
Session オブジェクトを作成します。そして、ドミノ・ディレクトリーにアクセスします。この場合、データベースが見つかった場合のみ続行します。
try
{
NotesThread.sinitThread();
Session s = NotesFactory.createSession();
Database db = s.getDatabase("","names.nsf");
if (db != null)
{
そして、新しい文書を作成し、文書にフォームの値を設定し、文書のフィールドを取得した値で初期化します。
Document doc = db.createDocument();
doc.replaceItemValue("Form", "Person");
doc.replaceItemValue("FirstName", fname);
doc.replaceItemValue("LastName", lname);
doc.replaceItemValue("OfficePhoneNumber", phone);
doc.replaceItemValue("MailAddress", email);
文書を保存し、文書やデータベース、Session オブジェクトで使用したシステム・リソースを解放します。(データベースが見つからない場合、Session
オブジェクトが解放される前にエラー・メッセージが発生します)
doc.save(true);
doc.recycle();
db.recycle();
}
else
{
pw.println("An error was encountered.");
}
s.recycle();
}
最後に、ドミノに関連する例外を処理し、それからスレッドを終了してブラウザーにメッセージを表示します。
catch (NotesException n)
{
pw.println("Notes Error: " + n.id);
pw.println("Description: " + n.text);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
NotesThread.stermThread();
}
pw.println(fname + " " + lname + " has been registered.");
pw.println("</body></html>");
}
}
サーブレット・プログラムの占める割合は、全体から見れば半分に過ぎません。次にドミノ・フォームの組み立てに注目しましょう。フォームはサーブレットに従わなければならず、サーブレットを指定して、新しく
HTML フォームのタグを追加しなければなりません。これのようにして、フォームからサーブレットへの提出を行います。フォームの閉じるタグはこのタグの前に配置される必要があります。これはドミノによって作成されたフォームのタグです。以下にフォームのデザインを示します。

次にフォームの先頭に現れ、フォームをサーブレットにリダイレクトする HTML
を示します。
[</form><form name="NotesNetExample" action="http://baseline2000:81/servlet/Example_3">]
大括弧 ([ and]) はテキストがパススルー HTML であることを表します。フォームの要素の名前属性はフォームに割り当てられます。この名前は
JavaScript からフォームの要素にアクセスするときや、フォームをサーバーに提出するときに使用されます。提出され、アクションが送信されたときにアクション属性はシグナルを発生します。
次の画面は Internet Explorer でオープンされたフォームです。フォーム・データは提出時にサーブレットに送信されます。
サーブレットとエージェントの選択は明確に決定できるものではありません。両者ともに
Java をサポートしているため、言語は問題ではありません。それぞれに長所があり、またドミノが両者をサポートしているという点が重要です。どちらを選択するかという決定は開発者に委ねられます。拡張性のある
Web の開発という点や WebSphere の強力なサーブレット・マネージャーを使用したいがためにサーブレットのほうを好むかもしれません。一方、経験豊富なドミノの開発者は堅牢なドミノ・エージェントの環境を好むでしょう。選択はあなたにかかっています。

著者について
アンソニー・パットンは、Java、XML、HTML 及びドミノのような、様々なテクノロジーを使って仕事をしています。彼は、「Practical
LotusScript」 や 「Domino Development With Java」の著者で両者とも Manning
Publications から手に入れられます。また、彼は熱烈なフィラデルフィア・スポーツのファンです。彼と連絡を取るには
asp01@aye.net までメールをお送りください。
|
 |
|
|