GlassFish アプリケーション・サーバーの相違点このセクションでは、ソースと対象の GlassFish アプリケーション・サーバーとの間での、 Java EE インプリメンテーションにおける相違に関する情報を記載しています。
ejb-jar.xml ファイル内に記載されている、セッション又は、エンティティビーンの説明は、オプションの <ejb-ref> にエントリーすることができます。この ejb-ref タグは、オプションの <ejb-link> タグを順に保管します。WebLogic 6.x は、 ejb-ref タグのエントリーである強制的な <ejb-ref-name> よりも <ejb-link> タグを優先します。これは、ある特定のビーンとマッチしない weblogic-ejb-jar.xml と ejb-jar.xml ファイルに ejb-ref-name がエントリーされている場合に発生します。 より詳細な ejb-jar.xml ファイル 内における ejb-link タグの記述位置は、 WebLogic 6.x では weblogic-ejb-jar.xml 内における ejb-ref-name のエントリーを不適切にします。マイグレーションツールは、 weblogic-ejb-jar.xml ファイルから、 sun-ejb-jar.xml ファイルを生成します。生成された sun-ejb-jar.xml ファイルの利用は、 GlassFish アプリケーション・サーバー上に、モジュールを展開することの妨げとなります。 次の例では、 WebLogic 6.x とマッチしない ejb-ref-name エントリーの場所を見せています。因みに、 WebLogic 6.x では有効な、 DD の設定内容があります。 ejb-jar.xml ファイルの設定内容は次のとおり : <session> <description>This is the Cart ejb </description> <display-name>The Cart </display-name> <ejb-name>TheCart</ejb-name> <home>com.sun.j2ee.blueprints.shoppingcart.cart.ejb.ShoppingCartHome</home> <remote>com.sun.j2ee.blueprints.shoppingcart.cart.ejb.ShoppingCart</remote> <ejb-class>com.sun.j2ee.blueprints.shoppingcart.cart.ejb.ShoppingCartEJB </ejb-class> <session-type>Stateful</session-type> <transaction-type>Container</transaction-type> <ejb-ref> <ejb-ref-name>ejb/catalog/Catalog</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <home>com.sun.j2ee.blueprints.shoppingcart.catalog.ejb.CatalogHome</home> <remote>com.sun.j2ee.blueprints.shoppingcart.catalog.ejb.Catalog</remote> <ejb-link>TheCatalog</ejb-link> </ejb-ref> </session> weblogic-ejb-jar.xml ファイルのコンテンツについては次のとおりです。Note the differences shown in bol;dface. <weblogic-enterprise-bean> <ejb-name>TheCart</ejb-name> <stateful-session-descriptor/> <reference-descriptor> <ejb-reference-description> <ejb-ref-name>ejb/catalog</ejb-ref-name> <jndi-name>estore/catalog</jndi-name> </ejb-reference-description> </reference-descriptor> <jndi-name>estore/cart</jndi-name> </weblogic-enterprise-bean> この制約にからの回避方法は、 この問題に対して適切に、ソース側の DDs または、 生成された sun-ejb-jar.xml ファイルを修正することです。
Java EE RI において、全ての CMRs が、 LINK テーブルへのアプローチを利用することを、永続化されます。また一方で、 GlassFish アプリケーション・サーバーにおいて、 LINK テーブルは、 many-to-many の関連性を利用する必要があります。その他全ての場合、外部参照キーへのアプローチは、 関連性の永続化によって、要求されます。 もしソース側のアプリケーションが、one-to-many の関連をもつユーザーの LINK テーブルへのアプローチを持っていた場合、マイグレーションツールは、 LINK テーブルへのアプローチが損なわれないように保持して、アプリケーションを移行します。結果として、GlassFish アプリケーション・サーバー上には、期待された機能を持たないアプリケーションが移行されます。 この制約を克服する為に、アプリケーション移行前に、 外部参照キーへのアプローチによる LINK テーブルへのアプローチを変更します。これら変更は、アプリケーション向けに、データベーススキーマへ反映されなければなりません。
サーブレット / JSP では、ヘッダー情報は、出力ストリームによって確定された、レスポンスのボディ部の後にセットされる必要があります。また、これは、 cookie/session 管理によって、 ヘッダー情報の一部として、正しく保持します。もし cookie/session オブジェクトが、いくつかの HTML が、出力ストリームに確定された後で、操作 / 更新された場合、これは、喪失され、要求された見えなくなっている情報を更新します。これは概ね、 GlassFish アプリケーション・サーバーでは、 response オブジェクトのデフォルトバッファサイズによって決まります。例では、サーブレットよりも下位から用いられた、コードの一部分とみなしています。太字のコメントに注意を払ってください。 public void service(HttpServletRequest req, HttpServletResponse res) throws IOException { boolean cookieFound = false; Cookie thisCookie = null; res.setContentType("text/html"); PrintWriter out = res.getWriter(); Cookie[] cookies = req.getCookies(); //Get Cookie information for(int i=0; i < cookies.length; i++) { thisCookie = cookies[i]; if (thisCookie.getName().equals("CookieCount")) { cookieFound = true; break; } } if (cookieFound == false) { thisCookie = new Cookie("CookieCount", "1"); thisCookie.setMaxAge(60*1); res.addCookie(thisCookie); } out.println("<html><head>\n" + //Writing some html response "<title>Cookie Counter</title>\n" + "</head>\n" + "<body bgcolor=#ffffff> <font face=\"Comic Sans MS\" size+=4 color=red>" + "<center><h1>Cookie Counter</h1></center>"); pageCount++; out.println("<p><img src=\"/images/cookie.jpg\" align=left>"); out.println("<font color=blue>"); out.println("<p><br><br><br>This page has been visited " + pageCount + (pageCount==1?" time":" times") + " before.\n"); if (cookieFound) { //Manipulating Cookie again! int cookieCount = Integer.parseInt(thisCookie.getValue()); cookieCount++; thisCookie.setValue(String.valueOf(cookieCount)); //Updating Cookie information after //some response has been written to //the response buffer!Bad move. thisCookie.setMaxAge(10); res.addCookie(thisCookie); out.println("<p>You have visited this page " + thisCookie.getValue() + (cookieCount==1?" time":" times") + " within the past 10 seconds.\n"); } else { out.println("<p>Either you haven't visited this page recently, "+ "or your browser doesn't like cookies!\n"); } out.println("</body></html>"); } このコードは、異なるアプリケーション・サーバーで実行されている場合に、矛盾した機能を見せています。 この原因は、次の理由のとおり :
この制約を解決するため、バッファへ出力する前に、全てのヘッダを操作し、更新するように、サーブレット /JSP コードを修正します。 これは、サーブレット /JSP 仕様で解説されているとおり、正しい慣例です。次は、ひとつ前の例を修正したコードです。太字でハイライトされている部分が、修正の留意点です。 public void service(HttpServletRequest req, HttpServletResponse res) throws IOException { boolean cookieFound = false; Cookie thisCookie = null; res.setContentType("text/html"); PrintWriter out = res.getWriter(); Cookie[] cookies = req.getCookies(); //Get Cookie information for(int i=0; i < cookies.length; i++) { thisCookie = cookies[i]; if (thisCookie.getName().equals("CookieCount")) { cookieFound = true; break; } } if (cookieFound == false) { //Manipulating Cookie thisCookie = new Cookie("CookieCount", "1"); thisCookie.setMaxAge(60*1); res.addCookie(thisCookie); } int cookieCount = 0; if (cookieFound) { cookieCount = Integer.parseInt(thisCookie.getValue()); cookieCount++; thisCookie.setValue(String.valueOf(cookieCount)); //Update Cookie information before //some response is written to //the response buffer. //Good move!Truly portable code thisCookie.setMaxAge(10); res.addCookie(thisCookie); } out.println("<html><head>\n" + //Now Write your response "<title>Cookie Counter</title>\n" + "</head>\n" + "<body bgcolor=#ffffff> + "<font face=\"Comic Sans MS\" size+=4 color=red>" + "<center><h1>Cookie Counter</h1></center>"); pageCount++; out.println("<p><img src=\""+req.getContextPath()+ "/images/cookie.jpg\" align=left>"); out.println("<font color=blue>"); out.println("<p><br><br> + "<br>This page has been visited " + pageCount + (pageCount==1?" time":" times") + " before.\n"); if (cookieFound) { out.println("<p>You have visited this page " + thisCookie.getValue() + (cookieCount==1?" time":" times") + " within the past 10 seconds.\n"); } else { out.println("<p>Either you haven't visited this page recently, "+ "or your browser doesn't like cookies!\n"); } out.println("</body></html>"); out.close(); }
HttpServletRequest インターフェースにある、 getCookies() メソッドは、 WLS5.1/WLS 6.x/Sun ONE Application Server 6.5 と GlassFish アプリケーション・サーバーでは、実装が異なります。このことは、次のサンプルコードと似たような、当メソッド呼び出すコードを包含した、サーバーサイドコンポーネントによって、一貫性の無い機能をもたらします。 getCookies public Cookie[] getCookies() クライアントがこの要求とともに送信したすべての Cookie オブジェクトを格納した配列を返します。クッキーが送信されなかった場合、このメソッドは null を返します。 戻り値: この要求に含まれるすべての Cookie の配列。要求にクッキーがない場合は null これは、まず最初に getCookies() メソッドを呼び出すと言うニュアンスで、 ( クッキーが存在しなかった場合 ) 、結果として null が返却されることを、以下のコードで示しています。このことは言い換えれば、 getCookies() メソッドを呼び出した次のラインの実行で、 NullPointerException と言う結果をもたらします。 Cookie[] cookies = req.getCookies(); <-----> Problem for(int i=0; i < cookies.length; i++) { <-----> NullPointerException here thisCookie = cookies[i]; if (thisCookie.getName().equals("CookieCount")) { cookieFound = true; break; } } 注意点 - また一方で、 WLS 5.1/6.x 及び Sun ONE AS 6.5 の一部で異常を出力します。言い換えると、 上記サンプルコードが、それらアプリケーション・サーバー上で動作することで、 getCookies() メソッドを最初に呼び出し、 null の変わりに( ドキュメンテーションに法る仕様として ) 空の配列が返却されるようにします。 ( 要素 0 の配列 ) GlassFish アプリケーション・サーバーでは、そういったケースが無いため、コードのこの部分が Java EE ドキュメンテーションにおける振る舞いで、 NullPointerException をスローしています。 Cookie[] cookies = req.getCookies(); if(cookies != null) <-----> Escape NullPointerException here { for(int i=0; i < cookies.length; i++) { thisCookie = cookies[i]; if (thisCookie.getName().equals("CookieCount")) { cookieFound = true; break; } } } 日本語翻訳: jack spallaw 英文 (翻訳したバージョン: 5) |