Jetty:WebAppContext.setParentLoaderPriority
jettyについての全投稿は/tag/jettyにあるので参照されたい
※この話には、よりラジカルな解決方法がある。Jetty:WebAppContext.setClassLoaderを参照のこと。
この問題の背景
あるプログラム(これを本体とする)の中でJettyを組み込みとして使い、ウェブアプリをホスティングする。つまり、通常のJavaプログラムとしても機能しつつ、ウェブサーバとしてウェブアプリをホスティングする。
しかし、ウェブアプリ内のコード自体にあらかじめアクセスしたいため(この理由は後述)、本体プログラムのライブラリとしてウェブアプリのWEB-INF/classesフォルダを指定しておく。これにより、WEB-INF/classes中のクラス(Aとする)に本体側からアクセスが可能になる。
さらに、ウェブアプリ側にはWEB-INF/libは入れない。なぜなら、クラスAが使用するライブラリは本体側になければならないからだ。必要なものはすべて本体側のライブラリとして指定しておく。
問題の発生
この状態でウェブアプリを走行させてみると、ウェブアプリで必要なライブラリは本体側にあり、既に本体側ローダで一部ロードされているが、当然ながらウェブアプリのclasses自体は本体側にはロードされていない。それらは、ウェブアプリ専用のローダでロードされる。
ここで、ウェブアプリがその中のクラスBを使用する場合で、その上位クラスCがライブラリにあり、Cが既に本体側でロードされていると困ったことになる。
本体側ローダのクラスCは、ウェブアプリローダのクラスBとは何の関係も無くなってしまう。字面上では、BはCのサブクラスだが、クラスローダが異なるため、無関係になってしまうのだ。
解決策として考えられること
二つの解決策が考えられた。
- ウェブアプリのclassesにあるクラスすべてをあらかじめ本体ローダでロードしておく。
- 何らかの方法で、ウェブアプリに独自ローダを使わせないようにJettyに細工する。
実際の解決策
Jettyのクラスローダに関する説明が、Jetty Classloadingにある。
これによれば、サーブレットの仕様としては、ウェブアプリ側のローダによるクラスロードが優先されるのだが、しかし、Jettyのオプションによって本体側ローダを優先することができるという。
このケースの場合、本体側のクラスパスにあるものとウェブアプリのclassesは全く同じものを指しているので、単純に本体側のローダを優先させればよい。
つまり、単純に、
WebAppContext warContext = new WebAppContext();
warContext.setParentLoaderPriority(true);
とすれば良いことがわかる。
ディスカッション
コメント一覧
まだ、コメントがありません