WebLogic Server アプリケーションの開発

     前  次    新しいウィンドウで目次を開く   
ここから内容の開始

WebLogic Server アプリケーションのクラスローディングについて

以下の節では、Java クラスローダの概要、および WebLogic Server Java EE アプリケーションのクラスローディングについて説明します。

 


Java のクラスローディング

クラスローダは、Java 言語の基本的モジュールです。クラスローダは、Java 仮想マシン (JVM) の構成要素で、クラスをメモリにロードし、実行時にクラス ファイルを検索してロードする役割があります。Java プログラミングを適切に行うためには、クラスローダとその機能をよく理解する必要があります。この節では、Java クラスローダの概要を説明します。

Java クラスローダの階層

クラスローダには、親クラスローダおよび子クラスローダからなる階層が含まれます。親クラスローダと子クラスローダの関係は、オブジェクトのスーパークラスとサブクラスの関係に似ています。ブートストラップ クラスローダは Java クラスローダ階層のルートです。Java 仮想マシン (JVM) では、ブートストラップ クラスローダを作成し、このクラスローダによって、Java 開発キット (JDK) の内部クラスおよび JVM に組み込まれている java.* パッケージがロードされます (java.lang.String などがロードされます)。

拡張クラスローダは、ブートストラップ クラスローダの子です。拡張クラスローダは、JDK の拡張ディレクトリにあるすべての JAR ファイルをロードします。この機能は、クラスパスにエントリを追加することなく JDK を拡張できるので便利です。ただし、拡張ディレクトリ内にあるものは、すべて完全に独立している必要があり、拡張ディレクトリに含まれているクラスまたは JDK クラスしか参照できません。

システム クラスパス クラスローダは、JDK 拡張クラスローダを拡張します。システム クラスパス クラスローダは、JVM のクラスパスからクラスをロードします。アプリケーション固有のクラスローダ (WebLogic Server のクラスローダなど) は、システム クラスパス クラスローダの子です。

注意 : Oracle で「システム クラスパス クラスローダ」と呼んでいるクラスローダは、多くの場合、WebLogic Server 以外の文脈上では、「アプリケーション クラスローダ」と呼ばれています。WebLogic Server におけるクラスローダについて説明する際には、Java EE アプリケーションまたはライブラリ関連のクラスローダ (「アプリケーション クラスローダ」と呼ぶ) と区別するために「システム」という用語を使用します。

クラスのロード

クラスローダでは、クラスのロード時に委託モデルを使用します。クラスローダの実装では、まずキャッシュをチェックして、要求されたクラスがすでにロードされていないか確認します。クラスを確認することで、ディスクからクラスを繰り返しロードする代わりに、キャッシュ メモリのコピーが使用されるのでパフォーマンスが向上します。キャッシュにクラスがなければ、現在のクラスローダが親にクラスを要求します。親クラスローダがクラスをロードできない場合のみクラスローダはクラスのロードを試行します。親と子両方のクラスローダにクラスがあると、親のクラスがロードされます。この委託モデルに従うのは、複数の同じ形式のコピーがロードされることを防ぐためです。同じクラスのコピーが複数あると、ClassCastException が発生する可能性があります。

クラスローダは、親クラスローダにクラスのロードを要求してから、クラスを実際にロードします。Web アプリケーションと関連する WebLogic Server のクラスローダは、クラスを親に要求する前にまずローカルをチェックするようにコンフィグレーションできます。これにより、Web アプリケーションは独自のサード パーティ クラスを使用できるようになります。このサード パーティ クラスは、WebLogic Server 製品の一部として使用することも可能な場合があります。「prefer-web-inf-classes 要素」節では、これについてより詳細に説明しています。

prefer-web-inf-classes 要素

weblogic.xml Web アプリケーションのデプロイメント記述子には、prefer-web-inf-classes 要素 (<container-descriptor> 要素のサブ要素) が含まれています。デフォルトでは、この要素は False に設定されています。この要素を True に設定すると、クラスローダの委託モデルが無効になり、Web アプリケーションからのクラス定義のほうが、より高度なクラスローダのクラス定義よりも優先的にロードされるようになります。このため、Web アプリケーションは独自バージョンのサード パーティ クラスを使用できるようになります。このクラスは、WebLogic Server の一部としても使用できる場合があります。「weblogic.xml デプロイメント記述子の要素」を参照してください。

この機能を使用する場合は、Web アプリケーションのクラス定義から作成されたインスタンスと、サーバの定義から作成されたインスタンスを混在させないように注意してください。これらのインスタンスが混在していると、ClassCastException が発生します。

コード リスト 8-1 は、prefer-web-inf-classes 要素とその定義およびデフォルト値を示します。

コード リスト 8-1 prefer-web-inf-classes 要素
/** 
* true の場合、Web アプリケーションの WEB-INF ディレクトリ内のクラスが、
* アプリケーションまたはシステム クラスローダにロードされるクラスに優先して
* ロードされる。
* @default false
*/
boolean isPreferWebInfClasses(); 
void setPreferWebInfClasses(boolean b);

実行中プログラムのクラス変更

WebLogic Server では、サーバが稼働中に EJB などのアプリケーション モジュールの新しいバージョンをデプロイできます。このプロセスは、ホットデプロイ、またはホット再デプロイと呼ばれ、クラスのロードと密接な関係があります。

Java クラスローダには、クラスをアンデプロイしたり、アンロードしたりする標準メカニズムはありません。また、新しいバージョンのクラスをロードすることもできません。実行中の仮想マシンでクラスを更新するには、変更されるクラスをロードしたクラスローダを、新しいクラスローダに置き換える必要があります。クラスローダが置き換えられると、そのクラスローダ (または、そのクラスローダの子に当たるクラスローダ) からロードされたすべてのクラスを、再ロードする必要があります。また、これらのクラスのインスタンスはすべて、再インスタンス化する必要があります。

WebLogic Server では、各アプリケーションに、システム クラスローダの子に当たるクラスローダからなる階層があります。これらの階層により、アプリケーションまたはアプリケーションの一部が、システムの他の部分に影響を与えることなく個別に再ロード可能です。「WebLogic Server アプリケーションのクラスローディング」で、このトピックについて説明しています。

 


WebLogic Server アプリケーションのクラスローディング

以下の節では、WebLogic Server アプリケーション クラスローダの概要を説明します。

WebLogic Server アプリケーションのクラスローディングの概要

WebLogic Server のクラスロードは、アプリケーションの概念に基づいています。アプリケーションは、通常、アプリケーション クラスを含むエンタープライズ アーカイブ (EAR) ファイルにパッケージ化されています。EAR ファイル内にあるものは、すべて同じアプリケーションの一部と見なされます。以下のファイルは、EAR の一部になることもでき、またスタンドアロンのアプリケーションとしてロードすることも可能です。

注意 :

EJB と Web アプリケーションを別々にデプロイすると、これらは 2 つのアプリケーションと見なされます。2 つのファイルをまとめて EAR ファイル内にデプロイすれば、1 つのアプリケーションとなります。したがって、複数のモジュールが同一アプリケーションの一部と見なされるためには、複数のモジュールをまとめて EAR ファイルにデプロイします。

すべてのアプリケーションは、独自のクラスローダ階層を受け取ります。この階層の親はシステム クラスパス クラスローダです。したがって、アプリケーションどうしが分離されているため、アプリケーション A からアプリケーション B のクラスローダおよびクラスを見ることはできません。階層クラスローダには、兄弟概念またはフレンド概念はありません。アプリケーション コードは、アプリケーション (またはモジュール) と関連するクラスローダでロードされたクラス、およびアプリケーション (またはモジュール) クラスローダの祖先に当たるクラスローダでロードされたクラスからしか見えません。したがって、WebLogic Server は同一の JVM 内の複数の分離したアプリケーションのホストになります。

アプリケーション クラスローダの階層

WebLogic Server では、アプリケーションのデプロイ時にクラスローダの階層が自動的に作成されます。この階層のルート クラスローダは、アプリケーション内のすべての EJB JAR ファイルをロードします。また、Web アプリケーション WAR ファイルごとに子クラスローダが作成されます。

Web アプリケーションによる EJB の呼び出しがよくあるため、WebLogic Server アプリケーション クラスローダ アーキテクチャでは JavaServer Page (JSP) ファイルおよびサーブレットからその親クラスローダ内の EJB インタフェースを見ることができるようになっています。また、このアーキテクチャでは EJB 層を再デプロイすることなく Web アプリケーションを再デプロイできます。実際には、EJB 層ではなく JSP ファイルおよびサーブレットを変更するほうが一般的です。

次の図は、WebLogic Server アプリケーションのクラスロード概念を示しています。

図 8-1 WebLogic Server のクラスロード

WebLogic Server のクラスロード

アプリケーションに EJB を使用するサーブレットと JSP が含まれる場合は、次の手順に従います。

WAR ファイルと JAR ファイルは別々にデプロイできますが、まとめて 1 つの EAR ファイルにしてデプロイすることにより、サーブレットと JSP から EJB クラスを検索できるようにクラスローダが配置されます。WAR ファイルと JAR ファイルを別々にデプロイすると、WebLogic Server ではそれらのファイルごとに兄弟のクラスローダを作成します。したがって、その WAR ファイルには EJB ホームおよびリモート インタフェースを含める必要があります。WebLogic Server では、EJB クライアントと実装クラスが異なる JVM にある場合と同じように、EJB 呼び出しに RMI のスタブ クラスとスケルトン クラスを使用します。 この概念については、次節の「アプリケーション クラスロードと、値渡しまたは参照渡し」で詳しく説明しています。

注意 : Web アプリケーション クラスローダには、JSP クラスを除く、Web アプリケーションのすべてのクラスが含まれます。JSP クラスは、独自のクラスローダを取得します。これは、Web アプリケーション クラスローダの子に当たります。これにより、JSP を個別に再ロードできます。

カスタム モジュール クラスローダの階層

アプリケーション用のカスタム クラスローダの階層を作成して、クラスの参照や再ロードを制御しやすくすることができます。この機能を実現するには、weblogic-application.xml デプロイメント記述子ファイルで classloader-structure 要素を定義します。

次の図は、WebLogic アプリケーションにおいてクラスローダがデフォルトではどのように構成されているかを示します。アプリケーション レベルのクラスローダは、すべての EJB クラスがロードされている場所にあります。各 Web モジュールについて、そのモジュールのクラス用の子クラスローダが個別に存在します。

簡素化のため、次の図では JSP クラスローダを示していません。

図 8-2 標準的なクラスローダの階層

標準的なクラスローダの階層

この階層は、EJB 呼び出し時に call-by-reference セマンティクスを使えるようになるため、大半のアプリケーションにとって最適です。また、これにより他のモジュールに影響を与えることなく Web モジュールを個別に再ロードできるようになります。さらに、Web モジュールの 1 つで実行されているコードが、任意の EJB モジュールからのクラスをロードできるようになります。これは、使用している EJB のインタフェースが Web モジュールに含まれることを防げるので便利です。これらの利点のいくつかは、厳密には Java EE に準拠していないことに注意してください。

カスタム モジュール クラスローダを作成できると、以下のことが可能になる代替的なクラスローダ構成を宣言するメカニズムが得られます。

クラスローダの階層の宣言

WebLogic 固有のアプリケーション デプロイメント記述子 weblogic-application.xml 内でクラスローダの階層を宣言できます。

この宣言の DTD は次のとおりです。

コード リスト 8-2 クラスローダの階層の宣言
<!ELEMENT classloader-structure (module-ref*, classloader-structure*)>
<!ELEMENT module-ref (module-uri)>
<!ELEMENT module-uri (#PCDATA)>

weblogic-application.xml の最上位要素には、省略可能な classloader-structure 要素が含まれます。この要素を指定しない場合は、標準のクラスローダが使用されます。また、定義の中に特定のモジュールを含めなかった場合、標準的な階層の場合と同じようにクラスローダを割り当てられます。つまり、EJB モジュールはアプリケーションのルート クラスローダと関連付けられ、Web アプリケーション モジュールは独自のクラスローダを持ちます。

classloader-structure 要素により、classloader-structure スタンザのネスティングが可能になって、クラスローダの任意階層を記述できるようになります。現在は、3 レベルに制限されています。最も外側のエントリは、アプリケーション クラスローダを示します。リストされていないモジュールについては、標準的な階層であると仮定されます。

注意 : JSP クラスローダは、この定義スキームには含まれません。JSP は常に、所属する Web モジュールと関連のクラスローダの子クラスローダにロードされます。

DTD 要素の詳細については、「エンタープライズ アプリケーションのデプロイメント記述子の要素」を参照してください。

以下は、クラスローダの宣言例です (weblogic-application.xml の classloader-structure 要素で定義)。

コード リスト 8-3 クラスローダの宣言例
<classloader-structure> 
	<module-ref> 
		<module-uri>ejb1.jar</module-uri> 
	</module-ref> 
	<module-ref> 
		<module-uri>web3.war</module-uri> 
	</module-ref>
	<classloader-structure> 
		<module-ref> 
			<module-uri>web1.war</module-uri>  
		</module-ref> 
	</classloader-structure>
	<classloader-structure> 
		<module-ref> 
			<module-uri>ejb3.jar</module-uri>  
		</module-ref> 
		<module-ref> 
			<module-uri>web2.war</module-uri>  
		</module-ref>
		<classloader-structure> 
			<module-ref> 
				<module-uri>web4.war</module-uri>  
			</module-ref> 
		</classloader-structure> 
		<classloader-structure> 
			<module-ref> 
				<module-uri>ejb2.jar</module-uri> 
			</module-ref> 
		</classloader-structure>
	</classloader-structure>
</classloader-structure>

ネスティングの構成は、クラスローダの階層を示します。上記のスタンザにより、次の図に示す階層がもたらされます。

図 8-3 クラスローダの階層の例

クラスローダの階層の例

ユーザ定義のクラスローダの制約

ユーザ定義のクラスローダの制約により、再ロードの対象とモジュール間でのクラスの参照が制御しやすくなります。この特徴は主に開発者のためのものです。繰り返し開発が行われる場合には有用ですが、プロダクション環境で使用する目的の場合には再ロード機能の使用はお勧めしません。更新時に無効な要素が含まれると、実行中のアプリケーションが破損するおそれがあるためです。ネームスペースの分離とクラス参照のためのカスタム クラスローダの配置は、プロダクション環境で使用する場合においても容認できるものです。ただし、Java EE 仕様にはアプリケーションがいかなるクラスローダ構成にも依存してはならないと書いてあることに、プログラマは注意する必要があります。

一部のクラスローダ階層は、アプリケーション内のモジュールが、2 つの別個のアプリケーションにおけるモジュールのように動作する原因となることがあります。たとえば、EJB を独自のクラスローダに配置して個別に再ロードできるようにすると、Oracle が標準的なクラスローダ階層で提供している call-by-reference による最適化ではなく、call-by-value セマンティクスがもたらされることになります。また、カスタム階層を使用すると、参照が古いものになってしまう可能性があります。したがって、EJB モジュールを再ロードする場合は、呼び出し側モジュールも再ロードしてください。

ユーザ定義によるモジュール クラスローダ階層の作成には、いくつかの制約があります。これらについてはこれ以降の節で説明します。

サーブレット再ロードの無効化

カスタム クラスローダ階層を使用する場合は、その特定のアプリケーションにおける Web アプリケーションについては、サーブレットの再ロードは無効化されます。

ネスティングの深さ

ネスティングは、3 つのレベルまでに制限されています (アプリケーション クラスローダを含む)。ネスティングが深くなると、デプロイメント例外が発生します。

モジュール タイプ

カスタム クラスローダ階層は、現在は Web および EJB モジュールに限定されています。

重複エントリ

エントリが重複すると、デプロイメント例外が発生します。

インタフェース

標準の WebLogic Server クラスローダ階層により、EJB インタフェースがアプリケーション内のすべてのモジュールで利用可能になります。したがって、それ自体のモジュールにインタフェースが含まれていなくても、他のモジュールが EJB を呼び出せます。これが可能なのは、EJB は常にルート クラスローダにロードされ、その他のモジュールはすべてそのクラスローダを共有するか、そのクラスローダの子に相当するクラスローダを持つことになるためです。

カスタム クラスローダ機能があれば、呼び出される側のクラスが呼び出し側から見えないようにクラスローダ階層をコンフィグレーションすることが可能です。この場合には、呼び出し側モジュールにインタフェース クラスを含める必要があります。これは、別個のアプリケーションのモジュールに対して呼び出しを行っている場合の要件と同じです。

call-by-value セマンティクス

WebLogic Server に設けられた標準クラスローダ階層により、アプリケーション内のモジュール間での呼び出しで call-by-reference セマンティクスを使用することが可能となります。これは、呼び出し側が常に同じクラスローダまたは呼び出される側の子クラスローダを使用しているためです。この機能により、2 つのモジュールがクラスローダ ツリーにおける別々のブランチに存在するように、クラスローダ階層をコンフィグレーションすることが可能になります。この場合、call-by-value セマンティクスが使用されます。

処理中の作業

再ロードに必要となるクラスローダの切り替えは、複数モジュールに渡って原子性を保たないことに留意してください。実際、アプリケーションの更新は、一般に原子性を保ちません。この理由により、タイミングによっては、異なった処理中の操作 (変更が行われているときに発生している操作) が、異なったバージョンのクラスにアクセスすることになる可能性があります。

開発用途のみ

development-use-only 機能は、開発に使用することが意図されています。更新は原子性を保たないので、この機能はプロダクションに使用するには適していません。

実装クラスのための個々の EJB クラスローダ

WebLogic Server を使うと、他のモジュールを同時に再ロードして、EJB モジュール全体を再デプロイする必要なしに、個々の EJB モジュールを再ロードできます。この機能は、現在 JSP が WebLogic Server サーブレットのコンテナに再ロードされている方法に類似しています。

EJB クラスはインタフェースを通じて呼び出されるため、個々の EJB 実装クラスをそれ自身のクラスローダにロードすることが可能です。このようにして、これらのクラスは EJB モジュール全体を再デプロイすることなく個別に再ロードできます。次の図は、単一の EJB モジュールのクラスローダ階層の一例です。モジュールには、2 つの EJB (Foo および Bar) が含まれています。これは、前の節で説明した一般的なアプリケーション階層におけるサブツリーと考えられます。

図 8-4 単一の EJB モジュールのクラスローダ階層の例

単一の EJB モジュールのクラスローダ階層の例

展開されたアプリケーションのルートを基準とした相対的な場所にあるファイルの部分的な更新を実行するには、次のコマンドラインを使用します。

コード リスト 8-4 部分的ファイル更新の実行
java weblogic.Deployer -adminurl url -user user -password password 
-name myapp -redeploy myejb/foo.class

-redeploy コマンドの後で、更新したい展開アプリケーションのルートを基準として相対的にファイルのリストを指定します。これは、(上記のような) 特定の要素へのパスであっても、モジュール (または任意の要素およびモジュールのセット) へのパスであってもかまいません。次に例を示します。

コード リスト 8-5 更新のための相対ファイル リストの指定
java weblogic.Deployer -adminurl url -user user -password password 
-name myapp -redeploy mywar myejb/foo.class anotherejb

更新するファイル群を指定されると、システムは再デプロイの最小要件を計算しようとします。EJB impl クラスのみを再デプロイすると、そのクラスのみが再デプロイされることになります。EJB 全体 (上の例では anotherejb) を指定するか、または EJB ホーム インタフェースを変更して更新する場合、EJB モジュール全体の再デプロイが必要です。

クラスローダの階層によっては、この再デプロイで他のモジュールが再デプロイされることになる可能性があります。具体的には、他のモジュールが EJB クラスローダを共有しているか、(WebLogic Server の標準クラスローダ モジュールでのように) EJB のクラスローダの子クラスローダにロードされる場合は、これらのモジュールもまた再ロードされます。

アプリケーション クラスロードと、値渡しまたは参照渡し

最近のプログラミング言語では、パラメータを渡すときのモデルとして、値渡しと参照渡しがよく使用されます。値渡しの場合、パラメータおよび戻り値はメソッドの呼び出しごとにコピーされます。参照渡しの場合は、実際のオブジェクトを示すポインタ (または参照) がメソッドに渡されます。参照渡しでは、オブジェクトをコピーしなくてもよく、渡されたパラメータの状態を変更するメソッドも使用できるため、パフォーマンスが向上します。

WebLogic Server では、サーバ内のリモート メソッド インタフェース (RMI) 呼び出しのパフォーマンス向上のための最適化機能もあります。値渡しおよび RMI サブシステムのマーシャリングやアンマーシャリング機能を使用するのではなく、参照渡しを使用することによって、サーバがダイレクト Java メソッド呼び出しを行います。この方式により、パフォーマンスが大幅に改善され、EJB 2.0 ローカル インタフェースにもこの方式が採用されています。

RMI 呼び出しの最適化および参照呼び出しが使用されるのは、呼び出し側と呼び出された側が共に同じアプリケーションにある場合に限られます。通常、クラスローダが関係します。アプリケーションにはそれぞれ独自のクラスローダ階層があるため、どのアプリケーション クラスも両方のクラスローダに定義があり、複数のアプリケーション間で割り当てを行おうとすると ClassCastException エラーを受け取ります。この問題を回避するため、WebLogic Server では複数のアプリケーション間での呼び出しには、同じ JVM 内であっても値呼び出しを使用しています。

注意 : 複数アプリケーション間の呼び出しは、同一アプリケーション内の呼び出しに比べて遅くなります。したがって、モジュールは 1 つの EAR ファイルにまとめてデプロイし、高速の RMI 呼び出しおよび EJB 2.0 ローカル インタフェースを使用できるようにしてください。

フィルタリング クラスローダの使用

WebLogic Server では、システム クラスパスにある JAR ファイルは WebLogic Server のシステム クラスローダによってロードされます。サーバ インスタンスの内部で実行されるすべてのアプリケーションは、システム クラスローダの子であるアプリケーション クラスローダ内にロードされます。このシステム クラスローダの実装では、アプリケーションは、システム クラスローダ内にすでに存在するさまざまなバージョンのサード パーティ製 jar を使用できません。すべての子クラスローダは親 (システム クラスローダ) に対して特定のクラス要求します。親に存在するクラスをロードすることはできません。

たとえば、com.foo.Baz というクラスが $CLASSPATH とアプリケーション EAR の両方に存在する場合は、$CLASSPATH にあるクラスがロードされて、EAR のクラスはロードされません。weblogic.jar$CLASSPATH にあるため、アプリケーションは WebLogic Server クラスをオーバーライドすることはできません。

以下の節では、フィルタリング クラスローダの定義と使用方法について説明します。

フィルタリング クラスローダとは

FilteringClassLoader は、デプロイメント記述子をコンフィグレーションして、特定のパッケージがシステム クラスローダによってロードされるのではなく、常にアプリケーションからロードされるように明示的に指定するためのメカニズムです。この機能によって、XercesAnt などの代わりのバージョンのアプリケーションを使用できるようになります。

FilteringClassLoader はアプリケーション クラスローダとシステムの間に位置します。システム クラスローダの子であり、アプリケーション クラスローダの親となります。FilteringClassLoaderloadClass(String className) メソッドをインターセプトして、weblogic-application.xml ファイルに指定されているパッケージのリストと className を比較します。パッケージと className が一致する場合、FilteringClassLoaderClassNotFoundException を送出します。この例外は、このクラスをアプリケーションからロードするようにアプリケーション クラスローダに通知するものです。

FilteringClassLoader のコンフィグレーション

FilteringClassLoader をコンフィグレーションして、特定のパッケージがアプリケーションからロードされることを指定するには、アプリケーションからロードされるパッケージのリストを記述している weblogic-application.xml に、prefer-application-packages 記述子要素を追加します。以下の例では、org.apache.log4j.* パッケージと antlr.* パッケージがシステム クラスローダではなくアプリケーションからロードされることを指定しています。

<prefer-application-packages>
  <package-name>org.apache.log4j.*</package-name>
  <package-name>antlr.*</package-name>
</prefer-application-packages>

リソースのロード順序

リソースのロード順序は、java.lang.ClassLoadergetResource() および getResources() メソッドがリソースを返す順序です。フィルタリングが有効になっている場合、この順序は、フィルタリングが無効な場合とは若干異なります。フィルタリングが有効になっているということは、FilteringClassLoader に 1 つまたは複数のパッケージ パターンがあることを意味しています。フィルタリングがない場合 (デフォルト)、リソースはクラスローダ ツリーの上から下へという順序で収集されます。たとえば、Web (1) がリソースを要求すると、リソースは「システム (3)、アプリケーション (2)、Web(1)」の順序でグループ化されます。図 8-5 を参照してください。

図 8-5 システム クラスローダの使用

       システム (3)

          |

         アプリケーション (2)

          |

         Web (1)

わかりやすくすると、たとえば、すべてのクラスローダに存在するリソース /META-INF/foo.xml の場合は、以下のような URL のリストが返されます。

   META-INF/foo.xml - システム クラスローダから (3) 
   META-INF/foo.xml - アプリケーション クラスローダから (2)
   META-INF/foo.xml - Web クラスローダから (1)

フィルタリングが有効になっている場合は、システム クラスローダのリソースよりも前に、FilteringClassLoader の子 (アプリケーション クラスローダ) から呼び出し側のクラスローダまでのリソースが返されます。図 8-6 では、(D)、(B)、および (A) のすべてのクラスローダに同じリソースが存在する場合、Web クラスローダがリソースを要求すると、リソースは次のような順序で取得されます。

   META-INF/foo.xml - アプリケーション クラスローダから (B)
   META-INF/foo.xml - Web クラスローダから (A)
   META-INF/foo.xml - システム クラスローダから (D)
注意 : FilteringClassLoader の下で、リソースはデフォルトの Java EE 委託モデルに従って返されます。FilteringClassLoader の親に存在するリソースのみが、返される列挙の最後に追加されます。
図 8-6 フィルタリング クラスローダ実装の使用

       システム (D)

          |

         FilteringClassLoader (filterList := x.y.*) (C)

          |

         アプリケーション (B)

          |

         Web (A)

アプリケーション クラスローダが同じリソースを要求した場合は、次のような順序になります。

   META-INF/foo.xml - アプリケーション クラスローダから (B)
   META-INF/foo.xml - システム クラスローダから (D)

getResource() の場合は、最初の記述子のみが返されて、getResourceAsStream() は最初のリソースの inputStream を返します。

 


モジュールおよびアプリケーション間のクラス参照の解決

アプリケーションでは、エンタープライズ Bean、サーブレットと JavaServer Pages、ユーティリティ クラス、およびサード パーティ製パッケージなど、さまざまな Java クラスを使用します。WebLogic Server では、個別のクラスローダにアプリケーションをデプロイして、独立を維持し、動的な再デプロイメントとアンデプロイメントを容易にします。このため、各モジュールが各クラスに個別にアクセスできるようにアプリケーションのクラスをパッケージ化する必要があります。場合によっては、一連のクラスを複数のアプリケーションまたはモジュールに格納する必要があります。この節では、アプリケーションを正常にステージングするために、WebLogic Server で複数のクラスローダを使用する方法について説明します。

リソース アダプタ クラス

各リソース アダプタの独自のクラスローダを使用してクラスがロードされるようになりました (Web アプリケーションの場合に類似)。その結果、アプリケーション アーカイブ (EAR ファイル) でリソース アダプタと一緒にパッケージ化されている Web アプリケーションおよび EJB などのモジュールは、リソース アダプタのクラスを参照できません。そのような参照が必要な場合は、リソース アダプタのクラスを APP-INF/classes に置く必要があります。また、これらのクラスを (JAR ユーティリティを使用して) アーカイブし、それらをアプリケーション アーカイブの APP-INF/lib に置くこともできます。

リソース アダプタ固有のクラスが WebLogic Server のシステム クラスパスにないことを確認してください。リソース アダプタ固有のクラスを Web モジュール (EJB、Web アプリケーションなど) と共に使用する必要がある場合、それらのクラスを該当するモジュールのアーカイブ ファイル (EJB に使用する JAR ファイルまたは Web アプリケーションに使用する WAR ファイルなど) にまとめます。

共有ユーティリティ クラスのパッケージ化

WebLogic Server は、EAR ファイル内で共有ユーティリティ クラスを格納できる場所を提供します。ユーティリティ JAR ファイルは APP-INF/lib ディレクトリに、個々のクラスは APP-INF/classes ディレクトリに置きます (JAR ファイルを /classes ディレクトリに置いたり、クラスを /lib ディレクトリに置いたりしないでください)。これらのクラスは、アプリケーションのルート クラスローダにロードされます。

この機能により、(どちらに置くかは標準の WebLogic Server クラスローダの階層によって変わりますが) システム クラスパス内にユーティリティ クラスを置く必要や、EJB JAR ファイル内にクラスを置く必要はなくなります。この機能を使用する場合は、次の節で説明するマニフェスト Class-Path を使う場合とは少し異なることに注意してください。この機能を使うと、クラス定義はアプリケーション全体で共有されます。マニフェスト Class-Path では、参照しているモジュールのクラスパスが単純に拡張されます。つまり、クラスのコピーが別々に各モジュールについて存在するということです。

マニフェスト クラスパス

Java EE 仕様では、クラスの補助的な JAR ファイルを必要とすることをモジュールで指定する手段としてマニフェスト Class-Path エントリが用意されています。このマニフェスト Class-Path エントリを使用するのは、EJB JAR ファイルまたは WAR ファイルの一部として追加の補助的な JAR ファイルがある場合に限られます。その場合、JAR ファイルまたは WAR ファイルの作成時に、必要な JAR ファイルを参照する Class-Path 要素と共にマニフェスト ファイルを含める必要があります。

utility.jar ファイルを参照する簡単なマニフェスト ファイルを以下に示します。

Manifest-Version: 1.0 [CRLF]
Class-Path: utility.jar [CRLF]

このマニフェスト ファイルの先頭行には、常に Manifest-Version 属性を指定する必要があり、次に改行 (CR | LF |CRLF)、そして Class-Path 属性が続きます。マニフェスト フォーマットの詳細については、http://java.sun.com/j2se/1.4/docs/guide/jar/jar.html#JAR を参照してください。

マニフェスト Class-Path エントリは、エントリが定義されている現在のアーカイブを基準として他のアーカイブを参照します。この構造により、複数の WAR ファイルおよび EJB JAR ファイルで、共通のライブラリ JAR を共有できます。たとえば、WAR ファイルに y.jar というマニフェスト エントリが含まれる場合、このエントリは、次のように WAR ファイルの次に (中ではない) 指定されなければなりません。

/<directory>/x.war
/<directory>/y.jars

マニフェスト ファイル自体は、META-INF/MANIFEST.MF のアーカイブに配置します。

詳細については、http://java.sun.com/docs/books/tutorial/jar/basics/manifest.html を参照してください。

 


Java EE ライブラリを使用したアプリケーションとモジュールの共有

Java EE ライブラリ機能により、複数のエンタープライズ アプリケーション間で、種類が異なる 1 つまたは複数の Java EE モジュールを簡単に共有できます。Java EE ライブラリは、デプロイメントに際して Java EE アプリケーション コンテナに登録される 1 つまたは複数のモジュールです。詳細については、「共有 Java EE ライブラリおよびオプション パッケージの作成」を参照してください。

 


システム クラスパスへの JAR の追加

WebLogic Server では、ドメイン ディレクトリ内に lib サブディレクトリが導入されています。このサブディレクトリを使用して、サーバの起動時に WebLogic Server システム クラスパスに 1 つまたは複数の JAR ファイルを追加できます。lib サブディレクトリは、サーバにデプロイされているすべてまたは大部分のアプリケーション、あるいは WebLogic Server 自体で必要とされ、かつほとんど変更されることのない JAR ファイルを格納するためのディレクトリです。たとえば、lib ディレクトリを使用して、ドメイン内の全デプロイメントで必要とされるサード パーティ ユーティリティ クラスを格納できます。また、WebLogic Server にパッチを適用する場合に、このディレクトリを使用することもできます。

lib ディレクトリは、ドメインにデプロイされている 1 つまたは 2 つのアプリケーションで JAR を共有したり、定期的に更新する必要がある JAR を共有したりする際の一般的な方法としては推奨できません。lib ディレクトリ内の JAR を更新する場合は、アプリケーションが変更を認識できるように、ドメイン内の全サーバを再起動する必要があります。複数のアプリケーション間で JAR ファイルまたは Java EE モジュールを共有する必要がある場合は、「共有 Java EE ライブラリおよびオプション パッケージの作成」で説明されている Java EE ライブラリ機能を使用します。

lib ディレクトリで JAR を共有するには、次の手順に従います。

  1. ドメイン内のすべてのサーバを停止します。
  2. 共有する JAR ファイルをドメイン ディレクトリの lib サブディレクトリにコピーします。次に例を示します。
  3. mkdir c:\bea\wlserver_10.3\samples\domains\wl_server\lib
    cp c:\3rdpartyjars\utility.jar
       c:\bea\wlserver_10.3\samples\domains\wl_server\lib
    注意 : WebLogic Server は、起動時に lib ディレクトリに読み込みアクセスできるようにする必要があります。
    注意 : 管理サーバは、lib ディレクトリのファイルを、リモート マシン上の管理対象サーバに自動的にコピーしません。管理対象サーバが、管理サーバと同じ物理ドメイン ディレクトリを共有していない場合、管理対象サーバ マシン上の domain_name/lib ディレクトリに手動で JAR ファイルをコピーする必要があります。
  4. ドメイン内の管理サーバと管理対象サーバを起動します。WebLogic Server は、lib ディレクトリにある JAR ファイルをシステム クラスパスに追加します。ファイルが複数の場合は、アルファベット順に追加されます。

ページの先頭       前  次