2. 移行ガイド

2.1. ソフトウェア条件

本章で対象とする移行元のAPサーバは以下のとおりです。

対象APサーバ バージョン
Tomcat 3.x
4.x
5.0.x
5.5.x
6.x
7.x
8.x

2.2. 移行の流れ

本章では、TomcatからWebOTXに移行する際の移行の流れを説明します。

2.2.1. 移行全体の流れ

TomcatからWebOTXに移行する場合、以下の流れで移行を行います。

  1. 移行元の設定情報を確認

    移行元のTomcat環境に設定した項目を確認します。

  2. 移行先の設定情報を設計

    移行元環境から確認した設定項目がWebOTXのどの項目に対応するか確認します。

  3. 移行するアプリケーションの準備 (※アプリケーションを移行する場合のみ)

    必要に応じてTomcatとWebOTXにおける設定や機能の対応を確認し、アプリケーションのソースコードに反映します。詳細は[ アプリケーションの準備 ]にて説明します。

  4. 移行先の環境にAPサーバをインストール

    移行先の環境にWebOTX Application Serverをインストールします。

  5. 移行先の環境に設定情報を反映

    設計した設定情報とアプリケーションを移行先の環境に反映します。

設定情報の確認(手順1)は移行元の環境で、APサーバのインストール(手順4)と設定情報の反映(手順5)は移行先の環境で行います。その他の作業については、任意の環境で行います。

設定情報の設計(手順2)や設定情報の反映(手順5)では、以下の点を考慮して作業を行う必要があります。

Tomcatの各バージョンと上記の対応は以下の通りです。

移行作業 Tomcat のバージョン 本章での説明
3.x 4.x 5.0 5.5 6.x 7.x 8.x
JDBCデータソースの設定 説明
セキュリティポリシーの設定 説明
Tomcatの差異による対応 説明
JavaVMオプションの設定 説明

○:作業要  △:条件により作業要  −:不要(対応済み)

2.2.2. アプリケーションの準備

移行元環境からアプリケーションを移行する場合、JDKの非互換やTomcatとWebOTXの違いを考慮してソースを確認し、必要に応じて修正します。

TomcatとWebOTXとの対比については、[ Tomcatとの対比 ]を参照ください。

そのほか、以下の点を考慮してソースを確認・修正を行う必要があります。

Tomcatの各バージョンと上記の対応は以下の通りです。

移行作業 Tomcat のバージョン 本章での説明
3.x 4.x 5.0 5.5 6.x 7.x 8.x
パッケージの設定 説明
log4jの設定 説明
nec-web.xmlの設定 説明

○:作業要  △:条件により作業要  −:不要(対応済み)

2.3. 移行作業

2.3.1. 移行元の設定情報を確認

移行元のTomcat環境に設定した項目を確認します。

2.3.2. 移行先の設定情報を設計

移行元環境から確認した設定項目がWebOTXのどの項目に対応するか確認します。WebOTXの設定項目については[ Webコンテナの設定 ]を、TomcatとWebOTXの対比については[ Tomcatとの対比 ]をご確認ください。

2.3.3. 移行するアプリケーションの準備

JDKの非互換やTomcatとWebOTXの違いを考慮してソースを確認し、必要に応じて修正を行います。

TomcatとWebOTXとの対比については、[ Tomcatとの対比 ]を参照ください。

そのほか、以下の点を考慮してソースの確認・修正を行う必要があります。

2.3.3.1. パッケージの設定

JSPで他のクラスをインポート (import) している場合には、パッケージの指定が必要です。

これまでJava2 SDK 1.3.1以前を使用していた場合は、そのJavacコンパイラの構文チェックが緩かったために問題とはなりませんでした。しかし、J2SE 1.4.0からは構文チェックが厳しくなり、パッケージを持たないJSPコードは、JSPをWebOTXに配備した後に行われるJSPコンパイルでエラーとなります。

J2SE 1.3.1以前のバージョンから移行する場合には、importのパッケージの指定を確認してください。

次のようにパッケージの指定のないimportはエラーとなります。

<%@ page import="Converter,ConverterHome" %>

importするクラスにパッケージの指定を追加して、importの指定をそれにあわせて修正してください。

本設定は、includeするファイルも含めて各ファイルで指定してください。


2.3.3.2. log4jの設定

Tomcatでは、Webアプリケーション毎にログ出力方法を制御する場合は、各Webアプリケーションの WEB-INF/classes 以下に log4j.properties または log4j.xml という名前で設定ファイルを配置します。そのほかに、システム全体で設定ファイルを指定する方法もあります。この場合、Tomcat3.x ならばTOMCAT_OPTS 、Tomcat4.x 以降ならばCATALINA_OPTS 環境変数へ指定します。

以下は、Tomcat4.xで、システム全体でlog4jの設定を行っている場合の移行の例です。WEB-INF/classes 配下に log4j の定義ファイルを含めている場合はこの設定は不要です。

【log4.configurationを使用した設定例 (tomcat4.xの例)】

環境変数への設定(unixの場合)

export CATALINA_OPTS="-Dlog4j.configuration=file:///home/foo/log4j.xml"

【運用管理コマンドでの設定(WebOTXの例)】

・アプリケーションをエージェントプロセスに配備した場合

otxadmin > create-jvm-options "-Dlog4j.configuration=file\:///${com.nec.webotx.instanceRoot}${file.separator}config${file.separator}{log4j 定義ファイル名}.xml"

・アプリケーションをプロセスグループに配備した場合

otxadmin > add-pg-javasystem-property --apgroup <APG名> --javasystemprop log4j.configuration --value file\:///${com.nec.webotx.instanceRoot}${file.separator}config${file.separator}{log4j 定義ファイル名}.xml

※ <APG名> にはアプリケーショングループ名が入ります。

Webアプリケーションでlog4j APIを呼び出して、利用するlog4j定義ファイルを読み込む方法についての説明は、ここでは省略します。

2.3.3.3. WebOTX独自のWebアプリケーション配備記述子(nec-web.xml)

Webアプリケーションには、Servlet仕様にしたがって配備記述子 (Deployment Descriptor) と呼ばれる実行の振る舞いを宣言するXML形式の設定ファイル (web.xml) を含めます。 WebOTX V6以降では、その標準のServlet仕様に規定されたweb.xml要素を拡張した、nec-web.xmlを追加しています。Tomcatの設定項目に対応するnec-web.xmlへの設定の詳細は[ Tomcat設定項目 > Tomcat設定項目との対応 ]を参照してください。

ライブラリのロードの設定を変更したい場合や、BASIC/FORM認証をする際のユーザ名や権限の設定を追加したい場合は、nec-web.xmlに該当する情報を設定しなければなりません。

BASIC認証、FORMベース認証を利用する場合の設定

WebOTXでは、BASIC認証かFORMベース認証を利用する場合、次の箇所を設定します。

【web.xmlの記述例(抜粋)】

<security-constraint>
   <display-name>Server Configuration Security Constraint</display-name>
      <web-resource-collection>
         <web-resource-name>Protected Area</web-resource-name>
          <!-- Define the context-relative URL(s) to be protected -->
          <url-pattern>*.jsp</url-pattern>
          <url-pattern>*.do</url-pattern>
          <url-pattern>*.html</url-pattern>
          <url-pattern>/WebAPManage/*</url-pattern>
      </web-resource-collection>
      <auth-constraint>
        <!-- Anyone with one of the listed roles may access this area -->
          <role-name>stRole</role-name>
      </auth-constraint>
  </security-constraint>

  <!-- Login configuration uses form-based authentication -->
  <login-config>
      <auth-method>FORM</auth-method>
        <realm-name>file</realm-name>
                    
        <form-login-config>
            <form-login-page>/login.jsp</form-login-page>
             <form-error-page>/error.jsp</form-error-page>
        </form-login-config>
    </login-config>

    <!-- Security roles referenced by this web application -->
    <security-role>
        <description>
             The role that is required to log in to the Administration Application
        </description>
       <role-name>stRole</role-name>
    </security-role>
【nec-web.xmlの記述例(抜粋)】

  <context-root>BasicAuthServlet24</context-root>
                
  <security-role-mapping>
    <role-name>stRole</role-name>
               
    <principal-name>admin3</principal-name>
                     
    <group-name>stGroup</group-name>
                  
  </security-role-mapping>

※ ロール名などをnec-web.xmlに指定する方法は、 [ アプリケーション開発 > Webアプリケーション > プログラミング・開発ガイド > Webアプリケーションのデプロイ> web.xmlデプロイメント記述子] の、[nec-web.xmlファイルの要素] をご覧ください。

クラスロード優先順位の設定

Webアプリケーションで利用するJavaのクラスを実行するためにロードを行う機能としてクラスローダがあります。

クラスローダには階層があります。上位のクラスローダでロードされたクラスからは下位のクラスローダでロードされたクラスは参照することができません。

逆に、下位のクラスローダでロードされたクラスからは、上位のクラスローダでロードされたクラスは参照することができます。

Webアプリケーションで使用するライブラリはWEB-IN/lib に配置します。複数のアプリケーションでライブラリを共有したい場合はWebOTX/libやdomain1/libに配置します

WebOTX のクラスローダの階層は次のようになります。

domain1/lib/ext
  ↑
WebOTX/modules(Webアプリケーションで使用するjarファイルはここには入れないで下さい)
  ↑
WebOTX/lib, domain1/lib
  ↑
classpath
  ↑
WEB-INF/lib

また、nec-web.xml のdelegate の設定により、ロードする優先順位を決定することができます。

同じ名前のライブラリがあると、競合が発生し、優先順位の高いパスに含まれるライブラリが利用されます。

ロードされるライブラリの優先順位はdelegate=true の場合は以下のようになります。delegate の設定はWebAP のWEB-INF/nec-web.xml で設定します。

domain1/lib/ext
  ↓
WebOTX/lib
  ↓
domain1/lib
  ↓
classpath
  ↓
WEB-INF/lib

delegate=false の場合は以下のようになります。

WEB-INF/lib
  ↓
domain1/lib/ext
  ↓
WebOTX/lib
  ↓
domain1/lib
  ↓
classpath


クラスローダの詳細は、[ 配備 > クラスローダ ] をご参照ください。

nec-web.xmlファイルの格納場所およびファイルの内容は次のとおりです。

${INSTANCE_ROOT}/applications/Webアプリケーション毎のディレクトリ/WEB-INF

【nec-web.xml】

<?xml version="1.0" encoding="UTF-8"?>
<nec-web-app xmlns="http://java.sun.com/xml/ns/j2ee">
  <context-root>context_name</context-root>
・・・Webアプリケーションのコンテキスト名
  <class-loader delegate="false"/>
・・・委譲モデル(ロード要求を受けた場合、まずは要求を親のクラスローダに委譲)を使用しない場合は、falseを指定
</nec-web-app>

※nec-web.xmlはアプリケーション配備時にアプリケーションディレクトリ内("<ドメインディレクトリ>/applications/<アプリケーション名>/WEB-INF" 配下)に自動的には生成されません。"<ドメインディレクトリ>/generated/xml/<アプリケーション名>/WEB-INF" 配下に生成されますので、必要に応じてコピーして使用してください。nec-web.xml が含まれない場合、Servlet のバージョンに関わらず delegate のデフォルト値は常に trueになります。

nec-web.xmlを変更した場合は、変更したnec-web.xmlを、WebアプリケーションのWEB-INF配下に再配置します。

WEB-INF下に配置後、次のいずれかの方法で配備を行ってください。

・WARファイルを作成して配備

・ディレクトリ指定で配備

配備については、[ Webアプリケーションのデプロイ ]をご覧ください。

利用する場合に設定が必要なパッケージ

Webアプリケーション内に配置したクラスのうちパッケージ名が以下で始まるクラスは参照することができません。この仕様はServlet仕様での勧告(javaxなどのJ2SE、J2EEクラスをWAR内のライブラリでオーバライドさせるべきではない)に基づくものです。詳細はServlet 2.4の9.7.2節を参照してください。
それにより、WEB-INF/lib配下のこれらのファイルを読み込む場合は以下の設定が必要になります。

対象パッケージ名
"javax"
"sun"
"org.xml.sax"
"org.w3c.dom"
"org.apache.taglibs.standard"
"com.sun.faces"

【nec-web.xmlでの設定方法】
<nec-web-app>タグの"property"に"validOverridableJavaxPackages"を追加します。(V9以降ではoverrideablejavaxpackagesも使用可能)
複数設定する場合はカンマで区切って指定します。
反映させるにはWebアプリケーションを更新して、更新したアプリケーションを配備し直してください。

※ org と指定した場合、 org.apache.xerces 等の指定したパッケージ配下全てに効果があります。

<?xml version="1.0" encoding="UTF-8"?>
<nec-web-app>
  <context-root>context_name</context-root>
  <class-loader delegate="true">
   <property name="validOverridableJavaxPackages" value="javax"/>
  </class-loader>
</nec-web-app>

※JAXB2.1を利用しているアプリケーションを動作させるためにもこの設定が必要となります。以下の例を参考にnec-web.xmlを追加してください。

<?xml version="1.0" encoding="UTF-8"?>
<nec-web-app>
  <context-root>context_name</context-root>
  <class-loader delegate="false">
   <property name="validOverridableJavaxPackages" value="javax,sun,org"/>
  </class-loader>
</nec-web-app>

※JavaVMシステムプロパティで、"com.nec.webotx.enterprise.overrideablejavaxpackages=パッケージ名"を設定をすることで全Webアプリケーションに対しての設定を行うこともできます。

設定方法の詳細については、[リファレンス > 設定 > Webコンテナ > Webコンテナ設定項目一覧 > JavaVMオプションで設定可能な項目一覧] を参照してください。

Java Server Faces(JSF)のアプリケーションを利用するための設定

JSF のアプリケーションを利用する場合、デフォルトでは delegate の値にかかわらず、WebOTX が持っている JSF の実装を利用して動作します。 ユーザのアプリケーションにバンドルされている JSF の実装を利用したい場合、 nec-web.xml に以下の例を参考に useBundledJsf=true の設定を追加してください。

【nec-web.xml】

<?xml version="1.0" encoding="UTF-8"?>
<nec-web-app>
  <context-root>context_name</context-root>
  <class-loader delegate="false"/>
 <property name="useBundledJsf" value="true"/>
</nec-web-app>

useBundledJsf=true を指定した場合、[ 利用する場合に設定が必要なパッケージ ]にあるパッケージのうち "javax.faces", "com.sun.faces" は自動で設定されるため、明示的に設定する必要はありません。

※アプリケーションで特定の <listener> を先に読み込ませる必要がある場合、 先に読み込ませたいリスナの定義を web.xml のリスナ定義の最初に追加してください。
例として、glassfish の JSF 実装のメソッド javax.faces.FactoryFinder.getFactory() メソッドを呼び出す場合、 jsf-core.tld に定義された ConfigureListener を最初にロードする必要があります。 この場合、web.xml に下記例のように設定を行ってください。

【web.xmlの記述例(抜粋)】

<context-param>
   …
</context-param>

<!-- 最初に追加 -->
<listener>
   <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>

<listener>
   <listener-class>nonjsp.lifecycle.XulServletContextListener</listener-class>
</listener>

<servlet>
   <servlet-name> ...
</servlet>

…
no-cache の設定

WebOTX ではセキュリティの制限がかかったアプリケーションへのアクセスの際に no-cache ヘッダを付加します。 V8.x 以降、デフォルトではセキュリティのかかったアプリケーション全体へのアクセスに対して no-cache ヘッダを付加しますが、 V7.x 以前の WebOTX ではセキュリティの範囲内だけに no-cache ヘッダを付加します。 例として、web.xml に以下の記述がある場合、V7.x 以前の WebOTX では *.jsp, *.do, *.html ファイルへのアクセスのみに no-cache ヘッダを付加しますが、V8.x以降 ではこのアプリケーション全体に対して no-cahce ヘッダを付加します。

【web.xmlの記述例(抜粋)】

<security-constraint>
   <display-name>Server Configuration Security Constraint</display-name>
      <web-resource-collection>
         <web-resource-name>Protected Area</web-resource-name>
          <!-- Define the context-relative URL(s) to be protected -->
          <url-pattern>*.jsp</url-pattern>
          <url-pattern>*.do</url-pattern>
          <url-pattern>*.html</url-pattern>
      </web-resource-collection>
      <auth-constraint>
        <!-- Anyone with one of the listed roles may access this area -->
          <role-name>stRole</role-name>
      </auth-constraint>
  </security-constraint>

  <!-- Login configuration uses form-based authentication -->
  <login-config>
      <auth-method>FORM</auth-method>
        <realm-name>file</realm-name>
                    
        <form-login-config>
            <form-login-page>/login.jsp</form-login-page>
             <form-error-page>/error.jsp</form-error-page>
        </form-login-config>
    </login-config>

    <!-- Security roles referenced by this web application -->
    <security-role>
        <description>
             The role that is required to log in to the Administration Application
        </description>
       <role-name>
stRole</role-name>
    </security-role>

この設定により、[ 注意制限事項 > 機能ごとの注意制限事項 > Webコンテナ > 注意事項 ]にある [ IEからSSL通信を行う場合、XMLドキュメントの取得に失敗する場合があることについて ]の現象を回避することができることがあります。

resource-ref の設定

アプリケーションからJDBCデータソースをルックアップする際に、引数として"java:comp/env/"から始まる文字列(環境ネーミングコンテキスト名)を用いている場合、 環境ネーミングコンテキスト名とJDBCデータソースの設定方法で指定したJNDI名(JNDI物理名)とのマッピングを nec-web.xml に resource-ref 要素 として記述する必要があります。

<resource-ref>
  <res-ref-name>環境ネーミングコンテキスト名("java:comp/env/"より後ろの部分)</res-ref-name>
  <jndi-name>JNDI物理名</jndi-name>
</resource-ref>

例えば、アプリケーション内で"java:comp/env/jdbc/MyOracle"という文字列を引数にルックアップしており、 で"jdbc/MyOracle"というJNDI物理名でJDBCデータソースを作成したのであれば、以下のように記述します。

<resource-ref>
  <res-ref-name>jdbc/MyOracle</res-ref-name>
  <jndi-name>jdbc/MyOracle</jndi-name>
</resource-ref>

2.3.4. 移行先の環境構築

移行先の環境に WebOTX Application Server をインストールします。

具体的なインストール手順については詳細は、各インストールガイド( WindowsLinuxHP-UX )を参照してください。

2.3.5. 移行先への設定情報の反映

設計した設定情報とアプリケーションを移行先の環境に反映します。

主な設定の反映方法は以下の通りです。アプリケーションの配備については、[ Webアプリケーションのデプロイ ]をご覧ください。

2.3.5.1. JDBCデータソースの設定

WebOTXのJDBCデータソースを利用するためには、WebOTX運用環境製品で提供している「統合運用管理ツール」か、標準で備わる「運用管理コマンド (otxadmin)」を利用します。ここでは、運用管理コマンドを利用する設定について説明します。

設定内容の詳細や運用機能の詳細は、WebOTXマニュアルの中の [ リファレンス > コマンドリファレンス > 運用管理コマンド(otxadmin) ]、 [ リファレンス > 設定 ] をご参照ください。

JDBCデータソースの設定方法

運用管理コマンドよりJDBCデータソースをJNDIに登録します。

以下は、WebOTXをインストールした際にデフォルトで作成されるドメイン「domain1」上でOracleデータベース・サーバを利用するJDBCデータソースを登録するコマンド例です。

otxadmin> create-jdbc-datasource --user admin --password adminadmin --port 6212 --host localhost --dataSourceType JDBCEX_Oracle --jdbcMajorVersion 3 --maxPoolSize 10 --jdbcUserName scott --jdbcPassword tiger --dataSourceName "jdbc:oracle:thin:@hostname:1521:ORCL" jdbc/MyOracle

※ 各引数の詳細は、WebOTXマニュアルの [ リファレンス > コマンドリファレンス > 運用管理コマンド(otxadmin) ]、 の "create-jdbc-datasource" を参照してください。

※"jdbc:oracle:thin:@hostname:1521:ORCL" および jdbc/MyOracle 部分は環境に合わせて変更してください。

登録が成功すると次のように表示されます。

> Command create-jdbc-datasource executed successfully.

現在の設定を確認する場合は、次のコマンドを実行します。

otxadmin> list-jdbc-datasources --user admin --password adminadmin --port 6212

アプリケーションからJDBCデータソースをルックアップする際に、引数として"java:comp/env/"から始まる文字列(環境ネーミングコンテキスト名)を用いている場合、 環境ネーミングコンテキスト名と、ここで指定したJNDI名(JNDI物理名)のマッピングをnec-web.xmlファイルに resource-ref 要素として記述する必要があります。 [ resource-ref の設定 ]を参照してください。

クラスパスの設定

Oracleデータベース・サーバに付属するJDBCドライバ (ojdbc6.jar) が配置されたディレクトリにクラスパスを設定します。 以下はdomain1ドメインにクラスパスを設定するコマンド例です。

現状のクラスパスを確認します。

otxadmin> get server.java-config.server-classpath

現状のクラスパスにJDBCドライバのクラスパスを追加設定します。

otxadmin> set server.java-config.server-classpath=…;/temp/ojdbc6.jar

※ "/temp/ojdbc6.jar"部分は環境に合わせて変更してください。

※ setコマンドは指定の値で上書きしますので、既存の設定値を含めて設定してください。

設定が完了したらドメインを再起動してください。

2.3.5.2. セキュリティポリシーの設定

Tomcatは、オプションなしで起動すると、Javaセキュリティ・マネージャを使用しない定義で動作します。セキュリティ・マネージャを使用しない場合、実行時にアクセス制御を行わないため、高速に処理できます。その反面、社会インフラでの利用に求められるサーバ・セキュリティが全く働かない問題があります。

WebOTXでは、デフォルトでセキュリティ・マネージャが動作します。これにより、Webアプリケーションが不用意に資源 (OS上のファイルや他システムへの接続など) にアクセスすることを制限することができます。ただし、意図した資源へのアクセスを許可する場合には、Javaセキュリティポリシーに追加設定する必要があります。

ここでは、Webアプリケーションが必要とする資源へのアクセスを許可させる方法について説明します。

セキュリティポリシーの設定方法

Webアプリケーションが、任意のディレクトリ/ファイルにアクセスする場合の設定を例に説明します。

  1. ドメインを停止します。

  2. Webアプリケーションが、「/Temp」ディレクトリとその配下のファイルの読み込みを行う場合、次のファイルに定義を追加します。

    【${INSTANCE_ROOT }/config/server.policy】

    ・・・
    // Basic set of required permissions granted to all remaining code
    grant {
    
    permission java.io.FilePermission "${/}Temp", "read";
    permission java.io.FilePermission "${/}Temp${/}-", "read";
    ・・・
    }
    ・・・
    

    上記では、「/Temp」ディレクトリへのreadの許可と、「/Temp」ディレクトリ配下のファイルのreadの許可を追加しています。

  3. 設定後に、ドメインを起動することで反映されます。

JDKのアクセス権とポリシーの構文については以下のサイトを参照してください。(Java SE 7の説明)

http://docs.oracle.com/javase/7/docs/technotes/guides/security/permissions.html

http://docs.oracle.com/javase/7/docs/technotes/guides/security/PolicyFiles.html

セキュリティ例外の調査方法

事前にアクセスするディレクトリ/ファイルなどが分かっている場合には、動作させる前にserver.policyに定義を追加できます。しかし、どのようなアクセスがあるか分からない場合には、Webアプリケーションを動作させてみて、セキュリティ例外メッセージから追跡します。

例えば、許可されない資源へのアクセスがあると、${INSTANCE_ROOT}/logs/server.logログファイルに次のような例外メッセージが記録されます。

access denied (java.io.FilePermission /Temp read)

この場合には、先に説明した「/Temp」ディレクトリへのreadを許可するポリシーの追加が必要になります。 さらに、次のようにJava VMのオプションを追加することによって、詳細な情報を確認することができます。 以下はdomain1ドメインにセキュリティ違反の詳細を確認するJava VMオプションを追加するコマンド例です。

otxadmin> create-jvm-options --user admin --password adminadmin --port 6212 --host localhost -Djava.security.debug=access\\:failure:

設定後、ドメインを再起動してください。詳細な情報がlogs/server.logに出力されますので、「denied」と記録されているものを確認し、セキュリティポリシーの追加を行ってください。

セキュリティポリシー設定の移行

Tomcatでのセキュリティポリシーの設定はconf/catalina.policyで行います。 WebOTXでのセキュリティポリシーの設定は${INSTANCE_ROOT }/config/server.policyで行います。現行のシステムでセキュリティポリシーを設定している場合は、この設定内容を移行します。

【conf/catalina.policy抜粋 (Tomcatの例)】

grant { 
    permission java.util.PropertyPermission "java.home", "read";
   :省略
};

【${INSTANCE_ROOT }/config/server.policy抜粋 (WebOTXの例)】

grant principal javax.management.remote.JMXPrincipal "admin" {
    :省略
    permission java.io.FilePermission "${java.home}${/}..${/}bin${/}-", "read,execute";
    :省略
};
2.3.5.3. Tomcatの差異による対応

Tomcatの各バージョンの差異により、WebOTXへの移行の際に対応が必要となる場合があります。

ここでは、各バージョンの差異とその対応方法について説明します。

また、WebOTX V6、V7のベースとなっているTomcatのバージョンは5.0、V8ではTomcat 6.0、V9ではTomcat7.0、V10ではTomcat8.5がベースとなっています。よって、V9以前からV10へ移行する際にもこれらの設定が必要になります。

Tomcat 5.0と Tomcat 5.5の差異

server.web-container.property.forwardRequestURLの値が変更されている

Tomcat 5.0以前からWebOTX V10へ移行する際にこの対応が必要になる場合があります。

Tomcat 5.0とTomcat 5.5の差異として、この値のデフォルト値が “original” → “forward” に変更されています。
WebOTX V6、V7 → V9の変更はTomcat 5.0 → 5.5の変更に合わせているため、対応が必要な場合は設定を行ってください。
設定方法の詳細は[ Tomcat設定項目との対応 ]をご覧ください。

Tomcat 5.5と Tomcat 6.0の差異

InvokerServletが機能しない

Tomcat 5.5以前からWebOTX V10に移行する際にこの対応が必要になる場合があります。

これはTomcat 5.5以前で機能していたInvokerServletの機能が、セキュリティ上の観点からTomcat 6.0以降ではデフォルトで動作しないようになっているためです。Tomcat8.5をベースにしているWebOTX V10ではこの問題が発生します。 この機能を使用する場合は下記の設定が必要になります。

【設定手順】

1) Webアプリケーションのweb.xmlのInvokeServletが定義されている事を確認します。

<servlet>
 <servlet-name>invoker</servlet-name>
 <servlet-class>org.apache.catalina.servlets.InvokerServlet</servlet-class>
 <init-param>
  <param-name>debug</param-name>
  <param-value>0</param-value>
 </init-param>
 <load-on-startup>2</load-on-startup>
</servlet>

…

<servlet-mapping>
 <servlet-name>invoker</servlet-name>
 <url-pattern>/servlet/*</url-pattern>
</servlet-mapping>

2) 次の方法で設定を追加します。

3) ドメインを再起動します。

[ Q&A > Webアプリケーションの実行エラーに関するQ&A ]の Q8 も参考にしてください。


JSPの実行時に例外が発生する場合がある

WebOTX V8より該当クラスのパッケージ名が変更されているため、JSPの実行時に例外が発生し、HTTPステータスコード500エラーが返却される場合があります。

org.apache.jasper.tagplugins.jstl.If

org.apache.jasper.tagplugins.jstl.core.If
その他の変更/削除されたパッケージ(クラス)は以下のとおりです。

[変更]
org/apache/commons/beanutils/ -> com/nec/webotx/org/apache/commons/beanutils/
org/apache/commons/collections/ -> com/nec/webotx/org/apache/commons/collections/
org/apache/commons/digester/ -> com/nec/webotx/org/apache/commons/digester/
org/apache/commons/el/ -> org/apache/taglibs/standard/lang/jstl/
org/apache/commons/el/parser/ -> org/apache/el/parser/
org/apache/commons/launcher/ -> com/nec/webotx/org/apache/commons/launcher/
org/apache/commons/logging/ -> com/nec/webotx/org/apache/commons/logging/
org/apache/commons/modeler/ -> com/nec/webotx/org/apache/commons/modeler/
org/apache/jasper/tagplugins/jstl/ -> org/apache/jasper/tagplugins/jstl/core/
org/apache/log4j/ -> com/nec/webotx/org/apache/log4j/

org/apache/jasper/util/FastDateFormat.class -> org/apache/catalina/util/FastDateFormat.class
org/apache/jasper/util/Queue.class -> org/apache/tomcat/util/collections/Queue.class
org/apache/jasper/util/SimplePool.class -> org/apache/tomcat/util/collections/SimplePool.class
org/apache/jasper/util/SystemLogHandler.class -> org/apache/tomcat/util/log/SystemLogHandler.class

[削除]
org/apache/commons/codec/
org/apache/commons/discovery/
org/apache/jasper/xmlparser/XercesEncodingDetector.class
org/apache/regexp/RETestCase.class
org/apache/taglibs/standard/tag/common/xml/JSTLPrefixResolver.class
org/apache/taglibs/standard/tag/common/xml/JSTLXPathAPI.class

Tomcat 6.0と Tomcat 7.0の差異

emptySessionPathの設定

Tomcat7では、emptySessionPathの設定が廃止され、sessionCookiePath="/" の設定により同等の動作をします。
WebOTX V9.2では、CookiePath="/"の設定で、指定します。

JSPコンパイル時に暗黙オブジェクトに対してfinal宣言が付く

Tomcat7では、以下の暗黙オブジェクトに対して final 宣言が付く変更が行われています。 そのため、これらの暗黙オブジェクトの値を変更することができません。

暗黙オブジェクト:
  request
  response
  pageContext
  application
  config
  page

WebOTX Media V9 Release 4以降からインストールした場合では、これらの暗黙オブジェクトの値を 変更するためのJVMオプション(com.nec.webotx.jasper.compiler.NO_FINAL_VARIABLES)を追加しています。 デフォルトは false で意味は以下のようになります。

 true:final宣言を付けない(WebOTX V8互換)
 false:final宣言を付ける

設定方法の詳細については、 [ リファレンス > 設定 > Webコンテナ > Webコンテナ設定項目一覧 > JavaVMオプションで設定可能な項目一覧] を参照してください。

JSPコンパイルのタグ属性重複エラーチェック

Tomcat7ではjspでカスタムタグをコンパイルする際、タグ属性の重複チェックが追加されました。
WebOTX V9以降では、タグ属性の重複チェックをON/OFFできるよう機能を強化しています。

【エラーとなるタグ記述の例】

    :
<%@ taglib uri="/WEB-INF/mytag.tld"  prefix="c" %>
    :
<c:mytest numAt="100" strAt="XYZ" strAt="ABC"/>
    :

Tomcat7ではタグ属性(strAt)が複数あるためエラーとなります。Tomcat6まではエラーにならず最後に設定した"ABC"が有効でした。

Tomcat 7.0と Tomcat 8.0の差異

リクエストパラメータデコード時の文字エンコード

Tomcat8.0でリクエストパラメータ取得する際、デコードに使用する既定の文字エンコードがISO-8859-1からUTF-8に変更されています。 WebOTX V10も既定の文字エンコードはUTF-8であるため、移行元のTomcat環境に合わせてuri-encodingパラメータを指定して回避する必要があります。

(*1)uri-encoding設定例 otxadmin> set server.network-config.protocols.protocol.http-listener.http.uri-encoding=ISO-8859-1

2.3.5.4. JavaVMオプションの設定

WebOTXは、Tomcatと同様にJavaVMのオプション設定をサポートしています。このため、既存のTomcatシステムでJavaVMオプションの設定を行っている場合はWebOTXにも同様の設定を行う必要があります。詳細は [ Java VMオプションのサポート ]を参照ください。

2.3.5.5. Cometの移行

TomcatやGrizzlyのCometを使用している場合は、今後のAPIの互換性が保障されるServlet 3.0を使用したCometに移行してください。
移行の方法を以下に説明します。

Tomcat CometからServlet API3.0 Cometへの移行
1クライアントが送信したメッセージを接続済みの全クライアントにレスポンスするチャットの様なアプリケーションを、 Tomcat CometからServlet 3.0 Cometに移行する場合を想定して移行方法を説明します。
移行ポイント Tomcat Comet Servlet3.0 の非同期APIへの移行
サーブレットクラス定義 Tomcat Cometはorg.apache.catalina.comet.CometProcessorをimplementsしています。 普通のServletと同じくHttpServletを継承し、CometProcessorのimplementsは削除します。

public class XXXServlet extends HttpServlet

次のいずれかを設定する必要があります
□@WebServlet に asyncSupported=true を指定。
例えば「@WebServlet(urlPatterns = {"/chat"}, asyncSupported = true)」

□web.xmlの<servlet> 要素の下に「<async-supported>true</async-supported>」を追加。
メッセージキュー メッセージキュー(1クライアントがリクエストしたデータをその他の非同期コンテキストに通知するためのキュー) を使用している場合はServlet3.0 Cometではそのまま流用可能です。
 
Tomcat Cometでメッセージキューを使用している場合はそのまま流用してください。
メッセージキューの実装例です。
BlockingQueue<String> messageQueue = new LinkedBlockingQueue<String>();

public void init(ServletConfig config) throws ServletException {
    super.init(config);
    Runnable notifierRunnable = new Runnable() {
        public void run() {
            try{
                while(true){ 
                    String cMessage = messageQueue.take();
                    for (AsyncContext ac : queue) {
                        try {
                            PrintWriter acWriter = ac.getResponse().getWriter();
                            acWriter.println(cMessage);
                            acWriter.flush();
                        } catch(IOException ex) {
                            queue.remove(ac);
                        }
                    }
                }
            }catch(InterruptedException e){
                log("messageQueue take error", e);
            }
        }
    };
    notifierThread = new Thread(notifierRunnable);
    notifierThread.start();
}

コネクションキュー コネクション(HttpServletResponseやPrintWriter等)のキューを管理している場合は、Servlet3.0では代わりにAsyncContextをキューで管理します。 HttpServletRequestのstartAsync()を実行した戻り値の AsyncContextをキューに登録します。
AsyncContext ac = request.startAsync();
this.queue.add(ac);
Timeout時間 TomcatではCometEventのsetTimeout()でタイムアウト時間を設定しています。
public void event(CometEvent event) throws IOException, ServletException {
    …
    if (event.getEventType() == CometEvent.EventType.BEGIN) {
    	event.setTimeout(30 * 60 * 1000); // 30分
Servlet3.0ではAsyncContextのsetTimeout()でタイムアウト時間を設定します
AsyncContext ac = request.startAsync();
ac.setTimeout(30 * 60 * 1000); // 30分
エラーコネクションの削除 Tomcat Cometで eventメソッドでのイベントがCometEvent.EventType.ERRORの場合やCometEvent.EventType.ENDの場合にコネクションを キューから削除している例です。
public void event(CometEvent event) throws IOException, ServletException {
  …
    } else if (event.getEventType() == CometEvent.EventType.ERROR) {
        synchronized (queue) {
            queue.remove(response);
        }
        event.close();
    } else if (event.getEventType() == CometEvent.EventType.END) {
        synchronized (queue) {
            queue.remove(response);
        }
        event.close();
    }
AsyncContext取得後にAsyncContextにAsyncListenerの実装をaddListener()します。
AsyncContext ac = request.startAsync();
ac.addListener(new AsyncListenerImpl());

Servlet3.0ではAsyncContextに登録するAsyncListenerの実装内のonError()とonTimeout()でコネクションをキューから削除します
class AsyncListenerImpl extends Thread implements AsyncListener{
  …
    @Override
    public void onError(AsyncEvent ae) throws IOException {
        synchronized (queue) {
            queue.remove(ae.getAsyncContext());
        }
    }

    @Override
    public void onTimeout(AsyncEvent ae) throws IOException {
        synchronized (queue) {
            queue.remove(ae.getAsyncContext());
        }
    }
}
init メソッド 色々な初期化処理が記述されていると思います。
以下は、メッセージキューを使うために、通知者用スレッドを開始している例です。
Runnable notifierRunnable = new Runnable() {
public void run() { 
  ... 
  while(true){ 
    cMessage = messageQueue.take(); 
    for (HttpServletResponse res : queue) { 
        try { 
            PrintWriter acWriter = res.getWriter(); 
            acWriter.println(cMessage); 
            acWriter.flush(); 
        } catch(IOException ex) { 
            queue.remove(ac); 
      ... 
    }
  }
}; 
notifierThread = new Thread(notifierRunnable); 
notifierThread.start();
initで行っている処理はそのまま移植します。
コネクションキューから取得されるコネクション情報はAsyncContextに変更します。

Runnable notifierRunnable = new Runnable() { 
public void run() { 
  ... 
  while(true){ 
    cMessage = messageQueue.take(); 
    for (AsyncContext ac : queue) { 
        try { 
            PrintWriter acWriter = ac.getResponse().getWriter(); 
            acWriter.println(cMessage); 
            acWriter.flush(); 
        } catch(IOException ex) { 
            queue.remove(ac); 
    ...
    }
  }
}; 
notifierThread = new Thread(notifierRunnable); 
notifierThread.start();
eventメソッド Tomcat Cometのイベントが発生した場合の処理が記述されています。
Servlet3.0では下記の対応を行います。
CometEvent<wbr>.EventType<wbr>.BEGIN eventメソッドでイベントタイプがCometEvent.EventType.BEGIN の場合の処理です。
if (event.getEventType() == CometEvent.EventType.BEGIN) {
    …
}
doGetメソッドやdoPostメソッドで処理を行います。
CometEvent<wbr>.EventType<wbr>.READ eventメソッドでイベントタイプがCometEvent.EventType.READ の場合の処理です。
if (event.getEventType() == CometEvent.EventType.READ) {
    …
}
doGetメソッドやdoPostメソッドでServletRequestの getInputStream()を使って ServletInputStreamを取得します。
CometEvent<wbr>.EventType<wbr>.ERROR eventメソッドでイベントタイプがCometEvent.EventType.ERROR の場合の処理です。
if (event.getEventType() == CometEvent.EventType.ERROR) {
    …
}
javax.servlet.AsyncListener を実装したクラスの onErrorメソッドに処理を記述します。
class AsyncListenerImpl extends Thread implements AsyncListener{
    …
    public void onError(AsyncEvent event) throws IOException {
        …
    }
}
CometEvent<wbr>.EventSubType<wbr>.TIMEOUT eventメソッドでイベントタイプがCometEvent.EventSubType.TIMEOUT の場合の処理です。
if (event.getEventSubType() == CometEvent.EventSubType.TIMEOUT) {
    …
}
javax.servlet.AsyncListener を実装したクラスの onTimeoutメソッドに処理を記述します。
class AsyncListenerImpl extends Thread implements AsyncListener{
    …
    public void onTimeout(AsyncEvent event) throws IOException {
        …
    }
}
doGet/doPost メソッド Tomcat Cometでは使用しません。 Tomcat Cometでイベントが CometEvent.EventType.BEGIN の場合に行っている処理をここで実装します。
実装される処理には以下の様なものがあります。 ・AsyncContextを生成します。
・タイムアウト時間を設定します。
・AsyncListenerを生成してAsyncContextに追加します。
・AsyncContextをキューに追加します。

final AsyncContext ac = req.startAsync();
ac.setTimeout(10 * 60 * 1000); 
ac.addListener(new AsyncListener() { 
    ... 
}; 
queue.add(ac);
destroy メソッド 以下の様な色々な後処理が実装されていると思います。
・キューのクリア。
・通知者スレッドの中止。

queue.clear();
notifierThread.interrupt();
Tomcat Cometからそのまま移植します。
Grizzly CometからServlet API3.0 Cometへの移行
1クライアントが送信したメッセージを接続済みの全クライアントにレスポンスするチャットの様なアプリケーションを、 Grizzly CometからServlet 3.0 Cometに移行する場合を想定して移行方法を説明します。
移行ポイント Grizzly Comet Servlet3.0 の非同期APIへの移行
サーブレットクラス定義 普通のServletと同じくHttpServletを継承しています。

public class XXXServlet extends HttpServlet
サーブレットクラスの継承はそのまま変えません。
public class XXXServlet extends HttpServlet

次のいずれかを設定する必要があります
□@WebServlet に asyncSupportedを指定。
例えば「@WebServlet(urlPatterns = {"/chat"}, asyncSupported = true)」

□web.xmlの<servlet> の下に「<async-supported>true</async-supported>」を追加。
メッセージキュー CometContextのnotify()の引数にメッセージを渡す事でGrizzlyが管理しているメッセージキューにメッセージを登録している例です。

CometContext cometContext = CometEngine.getEngine().getCometContext(this.contextPath);
cometContext.notify("[" + user + "]: " + message);
メッセージキューは独自に実装します。
メッセージキューの実装例です。
BlockingQueue<String> messageQueue = new LinkedBlockingQueue<String>();

public void init(ServletConfig config) throws ServletException {
    super.init(config);
    Runnable notifierRunnable = new Runnable() {
        public void run() {
            try{
                while(true){ 
                    String cMessage = messageQueue.take();
                    for (AsyncContext ac : queue) {
                        try {
                            PrintWriter acWriter = ac.getResponse().getWriter();
                            acWriter.println(cMessage);
                            acWriter.flush();
                        } catch(IOException ex) {
                            queue.remove(ac);
                        }
                    }
                }
            }catch(InterruptedException e){
                log("messageQueue take error", e);
            }
        }
    };
    notifierThread = new Thread(notifierRunnable);
    notifierThread.start();
}

コネクションキュー HttpServletResponse等にアタッチするためのCometHandlerを実装したクラスをCometContextに登録する事で、コネクションキューが管理されています。

CometHandlerImpl handler = new CometHandlerImpl();
handler.attach(response);
CometContext cometContext = CometEngine.getEngine().getCometContext(this.contextPath);
cometContext.addCometHandler(handler);
下記の例ではHttpServletResponseをアタッチしています。
public class CometHandlerImpl implements CometHandler<HttpServletResponse>{
  private  HttpServletResponse response;

  …

  public void attach(HttpServletResponse response){
    this.response = response;
  }
  …
}
コネクションキューは独自に実装します。
HttpServletRequestのstartAsync()を実行した戻り値AsyncContextをコネクションキューに登録します。

Queue<AsyncContext> queue = new ConcurrentLinkedQueue<AsyncContext>();

…

AsyncContext ac = request.startAsync();
this.queue.add(ac);
Timeout時間 CometContextのsetExpirationDelay()を行います。
CometContext cometContext = CometEngine.getEngine().register(contextPath);
cometContext.setExpirationDelay(30 * 60 * 1000);
コネクションキューに登録する前にAsyncContextのsetTimeout()を行います。
AsyncContext ac = request.startAsync();
ac.setTimeout(30 * 60 * 1000);
エラーコネクションの削除 Grizzly内部で管理しています。 AsyncContext取得後にAsyncContextにAsyncListenerの実装をaddListener()します。
AsyncContext ac = request.startAsync();
ac.addListener(new AsyncListenerImpl());

AsyncListenerの実装のonError()とonTimeout()で、コネクションキューからAsyncContextを削除します。

class AsyncListenerImpl extends Thread implements AsyncListener{
  …
  @Override
  public void onError(AsyncEvent event) 
  throws IOException {
    queue.remove(event.getAsyncContext());
  }

  @Override
  public void onTimeout(AsyncEvent event) 
  throws IOException {
    queue.remove(event.getAsyncContext());
  }
}
init メソッド CometEngineにcontextPathを登録しています。
タイムアウト時間を設定しています。

contextPath = config.getServletContext().getContextPath() + "/chat"; 
CometContext context = CometEngine.getEngine().register(contextPath);
context.setExpirationDelay(5 * 60 * 1000);
メッセージキューからメッセージを使うために、メッセージ通知用スレッドをつくって、開始します。

Runnable notifierRunnable = new Runnable() {
  public void run() {
    try{
      while(true){
        String cMessage = messageQueue.take();
        for (AsyncContext ac : queue) {
          try {
            PrintWriter acWriter = ac.getResponse().getWriter();
            acWriter.println(cMessage);
            acWriter.flush();
          } catch(IOException ex) {
            queue.remove(ac);
          }
        }
      }
    }catch(InterruptedException e){
      log("messageQueue take error", e);
    }
  }
};
notifierThread = new Thread(notifierRunnable);
notifierThread.start();
イベントハンドラ CometHandlerを実装したクラスがイベントハンドラです。
public class CometHandlerImpl implements CometHandler<HttpServletResponse>{
    ・・・

    public void onEvent(CometEvent event) 
    throws IOException{
        ・・・
    }
}
Sservlet3.0ではjavax.servlet.AsyncListener を実装したクラスがイベントハンドラです。
下記の対応を行います。
イベントハンドラ(onEvent) CometContextのnotify()を実行するとCometHandlerを実装したクラスのonEvent()がCometEvent.NOTIFYイベントで呼び出されます。
public class CometHandlerImpl implements CometHandler<HttpServletResponse>{
    ・・・

    public void onEvent(CometEvent event) 
    throws IOException{
        if ( event.getType() == CometEvent.NOTIFY ){
            String text = (String)event.attachment();
            PrintWriter writer = this.response.getWriter();
            writer.println(text);
            writer.flush();
        }

    }
}
Sservlet3.0ではメッセージキューから値を取り出しコネクションキューにあるコネクションに対してレスポンスを送信する処理を独自に作成して実装します。
initメソッドの例を参考にしてください。
イベントハンドラ(onInitialize) onInitialize()はリクエスト受信時に呼び出されます。
public class CometHandlerImpl implements CometHandler<HttpServletResponse>{
    ・・・
    
    public void onInitialize(CometEvent event) 
    throws IOException{
        this.response.setContentType("text/plain;charset=UTF-8");
        this.response.setCharacterEncoding("utf-8");

        PrintWriter writer = this.response.getWriter();
        writer.println("Welcome");
        writer.flush();
    }
}
Sservlet3.0ではdoGetメソッドやdoPostメソッドにて実装します。
イベントハンドラ(onTerminate) onTerminate()はCometEngineからコンテキストがunregister()される際に呼び出されます。
例ではコネクションのクローズを行っています。
public class CometHandlerImpl implements CometHandler<HttpServletResponse>{
    ・・・

    public void onTerminate(CometEvent event) 
    throws IOException{
        this.response.getWriter().close();
        CometContext context = 
            CometEngine.getEngine().getCometContext(contextPath);
        context.removeCometHandler(this);
    }
}
特に実装はありません。
イベントハンドラ(onInterrupt) onInterrupt()はタイムアウト時やクライアントから接続が閉じられた場合に呼び出されます。
例ではコネクションのクローズを行っています。
public class CometHandlerImpl implements CometHandler<HttpServletResponse>{
    ・・・

    public void onInterrupt(CometEvent event) 
    throws IOException{
        this.response.getWriter().close();
        CometContext context = 
            CometEngine.getEngine().getCometContext(contextPath);
        context.removeCometHandler(this);
    }
}
AsyncListenerの実装クラスのonError()やonTimeout()でコネクションキューからAsyncContextを削除する処理を実装します。
class AsyncListenerImpl extends Thread implements AsyncListener{
    ・・・

    public void onError(AsyncEvent event) throws IOException {
        queue.remove(event.getAsyncContext());
    }

    public void onTimeout(AsyncEvent event) throws IOException {
        queue.remove(event.getAsyncContext());
    }
}
doGet/doPost メソッド ■メッセージレスポンス用リクエストの場合
HttpServletResponseをアタッチした CometHandler実装クラスをCometContextに追加しています。
ChatListnerHandler handler = new ChatListnerHandler(); 
handler.attach(response); 
CometContext cometContext = CometEngine.getEngine().getCometContext(contextPath);
cometContext.addCometHandler(handler)
■メッセージリクエスト用リクエストの場合
CometContextのnotify(message)を実行しています。
CometContext cometContext = CometEngine.getEngine().getCometContext(this.contextPath);
cometContext.notify(message);
■メッセージレスポンス用リクエストの場合
AsyncContext にAsyncListenerの実装クラスを追加してコネクションキューにAsyncContextを追加します。
final AsyncContext ac = req.startAsync();
AsyncListenerImpl listener = new AsyncListenerImpl();
ac.addListener(listener);
queue.add(ac);
■メッセージリクエスト用リクエストの場合
メッセージキューにメッセージを登録します。
this.messageQueue.add(message);
destroy メソッド - ・Grizzly Cometで実装があればそのまま移植します。
・コネクションキューをクリアしてメッセージ通知用スレッドを中止します。

queue.clear();
notifierThread.interrupt();

2.4. 注意制限事項

2.4.1. 注意事項

2.4.1.1. Java SE SDKに関する注意事項

WebOTXが動作保証するJava SE SDK(JDK)に変更する場合、WebアプリケーションやWebアプリケーションが依存するライブラリが、特定のJava SE SDKに依存しないか動作確認を行ってください。

2.4.1.2. Tomcatとの差異