Oracle® Fusion Middleware Oracle WebLogic Server 10.3.6 Webアプリケーション、サーブレット、JSPの開発 11gリリース1 (10.3.6) B60993-07 |
|
![]() 前 |
![]() 次 |
この章では、WebLogic Server 10.3.6でWebLogic EJB-to-JSP統合ツールを使用して、JavaServer Page (JSP)でEJBを呼び出すためのJSPタグ・ライブラリを作成する方法について説明します。ここでは、読者が少なくともEJBとJSPの両方についてある程度の知識を持っていることを前提としています。
この章の内容は以下のとおりです。
EJB jarファイルを使用する場合、WebLogic EJB-to-JSP統合ツールでJSPタグ拡張ライブラリを生成します。このライブラリのタグは、そのjarファイルのEJBを呼び出すようにカスタマイズされます。クライアントから見た場合、EJBはそのリモート・インタフェースによって表されます。例:
public interface Trader extends javax.ejb.EJBObject { public TradeResult buy(String stockSymbol, int shares); public TradeResult sell(String stockSymbol, int shares); }
EJBを呼び出すWebアプリケーションの場合、JSPスクリプトレット(<% ... %>
)内からJavaコードを使用してEJBを呼び出すのが一般的な方法です。EJB呼出しの結果はHTMLとしてフォーマット化され、Webクライアントに提供されます。このアプローチは面倒で、エラーを引き起こしやすくなります。EJBの呼出しに必要なJavaコードは最も単純なケースでも非常に長く、HTML表現を担当するほとんどの設計者のスキルを超えています。
EJB-to-JSPツールは、Javaコードの必要性を排除することによって、EJB呼出しプロセスを簡素化します。かわりに、EJB用にカスタム生成されるJSPタグ・ライブラリを使用して、EJBを呼び出します。たとえば、上のTrader Beanのメソッドは、次のようにJSPで呼び出されます。
<%@ taglib uri="/WEB-INF/trader-tags.tld" prefix="trade" %> <b>invoking trade: </b><br> <trade:buy stockSymbol="BEAS" shares="100"/> <trade:sell stockSymbol="MSFT" shares="200"/>
この結果として生成されるJSPページは、より明確で直感的に理解できます。タグはEJBの各メソッドに対して(オプションで)生成されます。これらのタグは、対応するEJBメソッド呼出し用のパラメータに変換される属性を取ります。EJB呼出しの面倒な機構は隠され、生成されるタグ・ライブラリのハンドラ・コードの内部にカプセル化されます。生成されるタグ・ライブラリは、ステートレス・セッションBeanとステートフル・セッションBean、およびエンティティBeanをサポートします。これらのケースでは、タグの使用方法にそれぞれ若干の相違があります(後述の説明を参照)。
WebLogic EJB-to-JSP統合ツールは、コマンド・ライン・モードで、次のコマンドを使用して実行できます。
java weblogic.servlet.ejb2jsp.Main
またはグラフィカル・モードで次のようにします。最も単純なEJB以外は、グラフィカル・ツールを使用する方法が適しています。
次のようにグラフィカル・ツールを呼び出します。
java weblogic.servlet.ejb2jsp.gui.Main
最初は、Webアプリケーションによってejb2jspプロジェクトがロードされません。新しいプロジェクトを作成するには、「ファイル」>「新規」メニューを選択し、ファイル選択欄を参照してEJB jarファイルを見つけ、そのファイルを選択します。初期化が済んだら、ejb2jspプロジェクトを修正、保存、および再ロードできます。
生成されるタグ・ライブラリの構成は単純です。jarファイル内のEJBのメソッドごとに、そのメソッドと同名のJSPタグが生成されます。各タグには、対応するメソッドのパラメータと同数の属性を指定できます。
新しいEJB jarがロードされると、統合ツールはEJBのホーム・インタフェースとリモート・インタフェース用のJavaソース・ファイルを見つけようとします。これは、変換ツールはEJBクラスを参照するのみでタグを生成できますが、それらのタグ(対応するEJBメソッドがパラメータを取る)に意味のある属性名を割り当てることができないからです。「WebLogic EJB-to-JSP統合ツールの概要」のTraderの例では、EJB jarがロードされると、変換ツールはTrader.java
というソース・ファイルを探します。続いてこのファイルが解析され、buy()
メソッドがstockSymbol
およびshares
パラメータを取ることが検出されます。これにより、対応するJSPタグは適切な名前が付けられた属性(buy()
メソッドのパラメータに対応する)を持つようになります。
新しいEJB jarがロードされると、変換ツールは、EJB jarが存在するディレクトリとソース・ディレクトリが同じであるという前提で動作します。この前提に当てはまらない場合でも、エラーは致命的ではありません。新しいプロジェクトのロード後に、「プロジェクト・ビルド・オプション」パネルで、「EJBソース・パス」要素を調節して適切なディレクトリを指定できます。次に、「ファイル」>「属性の解決」メニューを選択して、解決プロセスを再実行します。
インタフェース・クラスに対応するjavaソース・ファイルを探すときに、統合ツールは指定されたディレクトリと、そのインタフェースのJavaパッケージによって示唆されるサブディレクトリの両方を検索します。たとえば、my.ejb.Trader
の場合、指定されたディレクトリがC:/src
であれば、統合ツールはC:/src/Trader.java
とC:/src/my/ejb/Trader.java
の両方を検索します。
ソース・ファイルへのアクセスは必須ではありません。統合ツールを使用することにより、プロジェクトの各タグの属性名を常に変更できます。しかし、EJBのパブリック・インタフェースのソース・ファイルの解析は、意味のある属性名を割り当てるための最も迅速な方法として開発されました。
このパネルは、プロジェクトの構築に必要なローカル・ファイル・システムに関連するすべてのパラメータを設定するために使用します。Javaコンパイラ、生成されるJSPタグ・ハンドラのJavaパッケージ、およびプロジェクト構築後に生成されるJavaコードを保持するかどうか(デバッグに役立つ)を指定します。
また、このパネルでは、タグ・ライブラリ出力の種類を指定できます。Java EE Webアプリケーションで使用する場合、タグ・ライブラリは次の2通りの方法のいずれかでパッケージ化する必要があります。1つは別個のクラス・ファイルとタグ・ライブラリ記述子(.tld
)ファイルで、もう1つは単一のtaglib jarファイルです。いずれかの出力タイプを[Output Type]プルダウン・メニューで選択します。開発およびテストのためには、DIRECTORY出力をお薦めします。jarファイルは、WebLogic ServerのWebアプリケーションを再デプロイしなければ上書きできないからです。
DIRECTORYまたはJARのいずれかについて、出力先を適切に選択して、タグ・ライブラリがWebアプリケーションによって検索されるようにします。たとえば、ディレクトリC:/mywebapp
をルートとするWebアプリケーションでタグ・ライブラリを使用する場合、「DIRECTORYクラス」フィールドには次のように指定する必要があります。
C:/mywebapp/WEB-INF/classes
また、「DIRECTORY .tldファイル」フィールドには次のように指定する必要があります。
C:/mywebapp/WEB-INF/trader-ejb.tld
前述のソース・パスも「ビルド・オプション」パネルで編集します。タグ・ライブラリがコアWebLogic ServerまたはJava EE APIに存在しない他のクラスに依存する場合は、「追加クラスパス」フィールドを使用できます。通常、このフィールドには何も追加する必要はありません。
エラーや競合によって、プロジェクトの構築に失敗する場合があります。この項では、これらのエラーの理由と解決方法について説明します。
構築情報の欠落: 「ビルド・オプション」パネル内の必須フィールドの1つに、javaコンパイラ、コード・パッケージ名、出力の保存先ディレクトリなどの値が指定されていない場合です。未指定のフィールドに値を指定しないと、構築を正常に行うことができません。
タグ名の重複: EJB jarがロードされると、統合ツールはEJBのメソッドごとにタグを記録します。このタグ名は、メソッド名と同じです。EJBがオーバーロード・メソッド(同名だがシグネチャが異なるメソッド)を持っている場合、タグ名が競合します。この競合を解決するには、これらのタグのいずれかの名前を変更するか、これらのタグの1つを無効にします。タグ名を変更するには、統合ツールの左ウィンドウのツリー階層を使用して問題のタグに移動します。右ウィンドウに表示されるタグ・パネルで、タグ名フィールドを変更します。タグを無効にするには、統合ツールの左ウィンドウのツリー階層を使用して問題のタグに移動します。右ウィンドウに表示されるタグ・パネルで、「タグの生成」ボックスの選択を解除します。EJB jarに複数のEJBが含まれている場合、Bean全体についてタグを無効にすることもできます。
意味のない属性名arg0、arg1...
。このエラーは、タグの妥当な属性名がEJBのインタフェース・ソース・ファイルから推測できない場合に発生します。このエラーを修復するには、プロジェクトの階層ツリーで問題のタグに移動します。次に、そのタグの下にある各属性ツリー・リーフを選択します。各属性について、ツールの右側に表示されるパネルの属性名フィールドに適切な名前を入力します。
属性名の重複: これは、複数の属性を指定できる1つのタグに同名の属性が2つ存在する場合に発生します。問題の属性に移動して、そのタグでそれぞれ一意になるよう名前を変更します。
生成されたEJBタグをJSPページで使用するには、そのページでタグ・ライブラリを宣言し、他のタグ拡張と同じようにそのタグを呼び出します。
<% taglib uri="/WEB-INF/trader-ejb.tld" prefix="trade" %> <trade:buy stockSymbol="XYZ" shares="100"/>
void以外の戻り値の型を持つEJBメソッドのために、「_return」という特別なオプションのタグ属性が組み込まれています。このタグが存在する場合、このメソッドから返される値は将来の処理のためにページ上で使用できます。
<% taglib uri="/WEB-INF/trader-ejb.tld" prefix="trade" %> <trade:buy stockSymbol="XYZ" shares="100" _return="tr"/> <% out.println("trade result: " + tr.getShares()); %>
プリミティブ数値型を戻すメソッドの場合、返される変数は、その型に対応するJavaオブジェクトです(「int」-> java.lang.Integer、など)。
EJB 2.0では、EJBホーム・インタフェースのメソッド(create()
またはfind()
以外)を使用できます。これらのホーム・インタフェース用のタグも生成されます。混乱を避けるため、新規プロジェクトがロードされるときに、EJBのホームの各メソッドに対応するタグの先頭に「home-」
という文字列が付加されます。必要な場合は、これらのメソッドの名前を変更できます。
「ステートフル」なBeanの一般的な用途は、Beanのホーム・インタフェースからそのインスタンスを取得し、単一のBeanインスタンスの複数のメソッドを呼び出すことです。このプログラミング・モデルも、生成されるタグ・ライブラリに保存できます。ステートフルEJBメソッド用のメソッド・タグは、EJBホーム・インタフェースの(そのホームのfind()
またはcreate()
に対応する)タグの内部に配置する必要があります。find/createタグの内部に存在するすべてのEJBメソッド・タグは、終了タグによって検索または作成されるBeanインスタンスで処理されます。ステートフルBeanのメソッド・タグがそのホームのfind/createタグで閉じられていない場合、実行時例外が発生します。たとえば、次のEJBが存在するとします。
public interface AccountHome extends EJBHome { public Account create(String accountId, double initialBalance); public Account findByPrimaryKey(String accountID); /* find all accounts with balance above some threshold */ public Collection findBigAccounts(double threshold); } public interface Account extends EJBObject { public String getAccountID(); public double deposit(double amount); public double withdraw(double amount); public double balance(); } Correct tag usage might be as follows: <% taglib uri="/WEB-INF/account-ejb.tld" prefix="acct" %> <acct:home-create accountId="103" initialBalance="450.0" _return="newAcct"> <acct:deposit amount="20"/> <acct:balance _return="bal"/> Your new account balance is: <%= bal %> </acct:home-create>
find/createタグで「_return」属性が指定されている場合、検索/作成されたEJBインスタンスを参照するページ変数が作成されます。エンティティBeanの検索メソッドも、EJBインスタンスのコレクションを戻す場合があります。Beanのコレクションを戻すメソッドを呼び出すホーム・タグは、そのコレクションのBeanごとにタグ本体で繰り返されます。「_return」が指定されている場合、それはその繰返しの内部の現在のBeanに設定されます。
<b>Accounts above $500:</b> <ul> <acct:home-findBigAccounts threshold="500" _return="acct"> <li>Account <%= acct.getAccountID() %> has balance $<%= acct.balance() %> </acct:home-findBigAccounts> </ul>
上の例では、残高が$500を超えるすべての口座BeanのHTMLリストが表示されます。
デフォルトでは、各メソッドのタグでは、そのすべての属性(メソッド・パラメータ)が各タグ・インスタンスに設定される必要があります。しかし、統合ツールでは、JSPタグに属性が指定されていない場合に備えて、「デフォルト」のメソッド・パラメータを指定することもできます。デフォルトの属性/パラメータは、EJB-to-JSPツールの属性ウィンドウで指定できます。パラメータのデフォルトは、単純なEXPRESSIONから取得されるか、より複雑な処理が必要な場合、デフォルトMETHOD本文が記述されます。たとえば、「WebLogic EJB-to-JSP統合ツールの概要」のTraderの例で、何も指定されていない場合、銘柄記号"XYZ"に対して"buy"タグを動作させるとします。この場合、"buy"タグの"stockSymbol"属性の属性パネルで、デフォルト属性値フィールドをEXPRESSIONに設定し、デフォルト式フィールドに"XYZ" (引用符を含む)と入力します。その結果、他の値が指定されていなければ、buyタグはstockSymbol="XYZ"属性が存在するかのように動作します。
また、"buy"タグのshares属性を0 - 100のランダムな数値にしたい場合、デフォルト属性値をMETHODに設定し、デフォルト・メソッド本文の領域に、int型("buy"メソッドの"shares"属性に対応する型)を戻すJavaメソッドの本文を記述します。
long seed = System.currentTimeMillis(); java.util.Random rand = new java.util.Random(seed); int ret = rand.nextInt(); /* ensure that it is positive...*/ ret = Math.abs(ret); /* and < 100 */ return ret % 100;
デフォルトのメソッド本文はJSPタグ・ハンドラの内部に現れるため、作成するコードはpageContext変数にアクセスできます。JSP PageContextから、現在のHttpServletRequestまたはHttpSessionへのアクセスを取得し、セッション・データまたはリクエスト・パラメータを使用してデフォルト・メソッド・パラメータを生成できます。たとえば、ServletRequestパラメータから"buy"メソッドの"shares"パラメータを取得するには、次のコードを記述します。
HttpServletRequest req = (HttpServletRequest)pageContext.getRequest(); String s = req.getParameter("shares"); if (s == null) { /* webapp error handler will redirect to error page * for this exception */ throw new BadTradeException("no #shares specified"); } int ret = -1; try { ret = Integer.parseInt(s); } catch (NumberFormatException e) { throw new BadTradeException("bad #shares: " + s); } if (ret <= 0) throw new BadTradeException("bad #shares: " + ret); return ret;
生成されるデフォルト・メソッドは例外をスローするものと見なされます。処理中に発生した例外は、JSPのerrorPageによって処理されるか、Webアプリケーションの登録済例外処理ページによって処理されます。