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) |