Jetty:WebAppContext.setClassLoader
jettyについての全投稿は/tag/jettyにあるので参照されたい
これはJettyをアプリ組み込みで使う際の話であることに注意。
Jetty:WebAppContext.setParentLoaderPriorityを利用してアプリを構成していたのだが、ある状況においては、アプリ側が確実に存在するはずのライブラリをロードできないことがある。
例えば以下だ。
java.lang.ClassNotFoundException: com.google.inject.servlet.GuiceServletContextListener
at java.base/java.net.URLClassLoader.findClass(Unknown Source)
at org.eclipse.jetty.webapp.WebAppClassLoader.findClass(WebAppClassLoader.java:510)
at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:441)
at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:403)
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(Unknown Source)
at java.base/java.security.SecureClassLoader.defineClass(Unknown Source)
at java.base/java.net.URLClassLoader.defineClass(Unknown Source)
at java.base/java.net.URLClassLoader.access$100(Unknown Source)
at java.base/java.net.URLClassLoader$1.run(Unknown Source)
at java.base/java.net.URLClassLoader$1.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.net.URLClassLoader.findClass(Unknown Source)
at org.eclipse.jetty.webapp.WebAppClassLoader.findClass(WebAppClassLoader.java:510)
どうもorg.eclipse.jetty.webapp.WebAppClassLoaderにバグがあるような気がするのだが、たしかではない。ともあれ、この解決方法としては、単純にJettyがウェブアプリごとに用意するクラスロードをやめさせ、システムクラスローダを使ってしまうという方法がある。
Jetty Classloadingの最後に記述がある。
単純に、以下のようにすればよい。
class SomeClass {
public void someMethod() {
WebAppContext warContext = new WebAppContext();
warContext.setClassLoader(SomeClass.class.getClassLoader());
}
}
こうすれば、コンテナ側(アプリ本体)と、その組み込みJetty上のウェブアプリのクラスローダが同一になるようだ。当然のことながら、「warContext.setParentLoaderPriority(true);」は不要になる。