GlassFish アプリケーション・サーバーの相違点

このセクションでは、ソースと対象の GlassFish アプリケーション・サーバーとの間での、 Java EE インプリメンテーションにおける相違に関する情報を記載しています。

  • WebLogic 6.x と GlassFish アプリケーション・サーバーとの間での、 <ejb-ref> の実装の相違

ejb-jar.xml ファイル内に記載されている、セッション又は、エンティティビーンの説明は、オプションの <ejb-ref> にエントリーすることができます。この ejb-ref タグは、オプションの <ejb-link> タグを順に保管します。WebLogic 6.x は、 ejb-ref タグのエントリーである強制的な <ejb-ref-name> よりも <ejb-link> タグを優先します。これは、ある特定のビーンとマッチしない weblogic-ejb-jar.xmlejb-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 ファイルを修正することです。

  • GlassFish アプリケーション・サーバーへの、アプリケーション移行の為の、Java EE レファレンス実装からの、管理コンテナ関連 (CMR) の利用。

Java EE RI において、全ての CMRs が、 LINK テーブルへのアプローチを利用することを、永続化されます。また一方で、 GlassFish アプリケーション・サーバーにおいて、 LINK テーブルは、 many-to-many の関連性を利用する必要があります。その他全ての場合、外部参照キーへのアプローチは、 関連性の永続化によって、要求されます。 もしソース側のアプリケーションが、one-to-many の関連をもつユーザーの LINK テーブルへのアプローチを持っていた場合、マイグレーションツールは、 LINK テーブルへのアプローチが損なわれないように保持して、アプリケーションを移行します。結果として、GlassFish アプリケーション・サーバー上には、期待された機能を持たないアプリケーションが移行されます。 この制約を克服する為に、アプリケーション移行前に、 外部参照キーへのアプローチによる LINK テーブルへのアプローチを変更します。これら変更は、アプリケーション向けに、データベーススキーマへ反映されなければなりません。

  • サーブレットと JSP の移行における、レスポンスバッファサイズの変化

サーブレット / 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>");  
}

このコードは、異なるアプリケーション・サーバーで実行されている場合に、矛盾した機能を見せています。 この原因は、次の理由のとおり :

  • ある特定のアプリケーション・サーバーのデフォルトレスポンスバッファサイズが、出力される、レスポンスバッファサイズよりも大きかった場合、コードの動作による、反映されるレスポンスの出力の後で、クッキー情報が更新されます。WebLogic 5.1 と WebSphere Application Server 4.0 でのデフォルトバッファサイズは、それぞれ、 8 KB と 4 KB です。とはいえ、それらアプリケーション・サーバー上でコードが作業する上で (4 KB 以下の Cookie オブジェクトが更新される以前に、このコードによってレスポンスを出力するバッファサイズ )、レスポンスの出力バッファサイズがデフォルトバッファサイズを超える場合、そのコードは他の例では有効的ではありません。
  • ある特定のアプリケーション・サーバーのデフォルトレスポンスサイズが、レスポンス出力バッファサイズよりも低い場合、 Cookie 情報は、出力レスポンスを消失した後で更新されます。 これはなぜなら、レスポンスがクライアントブラウザへ確定された後では、ヘッダー情報は設定できないからです。Sun ONE Application Server 6.5 でのデフォルトバッファサイズは、 0 KB です。そのため、このコードは、 GlassFish アプリケーションサーバ上で、整合性の取れた動作はしません。

この制約を解決するため、バッファへ出力する前に、全てのヘッダを操作し、更新するように、サーブレット /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();
  }
  • WLS5.1/6.x/Sun ONE Application Server 6.5 とGlassFish アプリケーション・サーバー間での HttpServletRequest の実装に関する相違点

HttpServletRequest インターフェースにある、 getCookies() メソッドは、 WLS5.1/WLS 6.x/Sun ONE Application Server 6.5 と GlassFish アプリケーション・サーバーでは、実装が異なります。このことは、次のサンプルコードと似たような、当メソッド呼び出すコードを包含した、サーバーサイドコンポーネントによって、一貫性の無い機能をもたらします。
サンプルコードを見る前に、サーブレット使用で定義されているこのメソッドがどんなものか、試してみましょう。J2EE 標準の WLS5.1 と Sun ONE Application Server 6.5 による J2EE 1.2.x と、J2EE 標準の WLS 6.x による J2EE 1.3.x の両方のドキュメンテーションに通じる API HttpServletRequest インターフェースにある getCookies() メソッドについては、次のとおり :

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)