問題
私たちは、外部のSOAPウェブサービスを呼び出したいカスタムログインプレアクションモジュールを開発しました。
Java 11にアップグレードした後、この外部SOAPウェブサービスを呼び出そうとすると、javax.xml.ws.spi.Provider
またはcom.sun.xml.ws.spi.ProviderImplに関する
エラーが発生します。
この問題の根本的な原因は、Java 11 JVMにおけるJAX-WS(java.xml.ws)の非推奨化である。
Java11でコードを実行するために、いくつかのオプションを試しましたが、以下のエラーが発生しました:
-
javax.xml.ws:jaxws-apiの依存関係を使用しています:
2023-08-14 11:17:15.934 ERROR [http-nio-8080-exec-5][CustomLoginPreAction:189] Error: javax.xml.ws.WebServiceException: Error while searching for service [javax.xml.ws.spi.Provider] javax.xml.ws.WebServiceException: Error while searching for service [javax.xml.ws.spi.Provider] at javax.xml.ws.spi.FactoryFinder$1.createException(FactoryFinder.java:61) at javax.xml.ws.spi.FactoryFinder$1.createException(FactoryFinder.java:58) at javax.xml.ws.spi.ServiceLoaderUtil.firstByServiceLoader(ServiceLoaderUtil.java:70) at javax.xml.ws.spi.FactoryFinder.find(FactoryFinder.java:89) at javax.xml.ws.spi.Provider.provider(Provider.java:96) at javax.xml.ws.Service.(Service.java:112) [...ommited lines...] 原因: java.util.ServiceConfigurationError: javax.xml.ws.spi.Provider: com.liferay.jaxws.osgi.bridge.Provider not a subtype at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:589) at java.base/java.util.ServiceLoader .hasNextService(ServiceLoader.java:589)ServiceLoader.fail(ServiceLoader.java:589) at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1237) at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1265) at java.base/java.util.ServiceLoader$2.hasNext(ServiceLoader.java:1300) at java.base/java.util.ServiceLoader$3.hasNext(ServiceLoader.java:1385) at javax.xml.ws.spi.ServiceLoaderUtil.firstByServiceLoader(ServiceLoaderUtil.java:63) ...106 more
- jakarta.xml.ws:jakarta.xml.ws-apiの依存関係を使用しています:
2023-08-13 17:31:06.035 ERROR [http-nio-8080-exec-10][CustomLoginPreAction:190] Error: jakarta.xml.ws.WebServiceException: Provider com.sun.xml.ws.spi.ProviderImpl not found jakarta.xml.ws.WebServiceException: Provider com.sun.xml.ws.spi.ProviderImpl not found at jakarta.xml.ws.spi.FactoryFinder$1.createException(FactoryFinder.java:35) at jakarta.xml.ws.spi.FactoryFinder$1.createException(FactoryFinder.java:32) at jakarta.xml.ws.spi.ServiceLoaderUtil.newInstance(ServiceLoaderUtil.java:76) at jakarta.xml.ws.spi.FactoryFinder.find(FactoryFinder.java:110) at jakarta.xml.ws.spi.Provider.provider(Provider.java:64) at jakarta.xml.ws.Service.(Service.java:82) [...ommited lines...] Caused by: java.lang.ClassNotFoundException: com.sun.xml.ws.spi.ProviderImpl at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1412) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1220) at com.liferay.shielder.container.internal.ShappClassLoaderBase.java:1220.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1220) at com.liferay.shielded.container.internal.ShieldedContainerClassLoader.findClass(ShieldedContainerClassLoader.java:79) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) at jakarta.xml.ws.spi.ServiceLoaderUtil.nullSafeLoadClass(ServiceLoaderUtil.java:62) at jakarta.xml.ws.spi.ServiceLoaderUtil.safeLoadClass(ServiceLoaderUtil.java:97) at jakarta.xml.ws.spi.ServiceLoaderUtil.newInstance(ServiceLoaderUtil.java:73) ...163 more
環境
- Liferay DXP 7.2
- Liferay DXP 7.3
- Liferay DXP 7.4
解像度
Java 11にアップグレードした後は、jakarta.xml.ws:jakarta.xml.ws-apiの依存関係を使用しなければならないが、ClassNotFoundExceptionエラーを回避するためには、次のようにしなければならない:
モジュールの依存関係を修正コンパイル時
jaxws-rt.jarライブラリをインクルードするために、com.sun.xml.ws:jaxws-rt
への依存関係を追加します。
Java 11にアップグレードした後、java.xml.ws
(JAX-WS)の依存関係をjakarta.xml.ws
+com.sun.xml.wsに
置き換える方法については、いくつかの例がある:
- https://eclipse-ee4j.github.io/metro-jax-ws/
- https://stackoverflow.com/questions/48204141/replacements-for-deprecated-jpms-modules-with-java-ee-apis、「JAX-WS (java.xml.ws)」のセクションをチェックする。
- https://www.baeldung.com/java-soap-web-service#jdk11maven-wsimport
実行時のクラスローダーの問題を修正
見つからない
これを避けるには、ウェブ・サービスを呼び出す前に現在のスレッドのクラス・ローダーに変更を加え、呼び出し後にそれを復元すればよい:
Thread currentThread = Thread.currentThread();
ClassLoader threadClassLoader = currentThread.getContextClassLoader();
ClassLoader correctClassLoader = this.getClass().getClassLoader();
try {
//現在のスレッドのクラスローダを変更します
currentThread.setContextClassLoader(correctClassLoader);
// ===> ここに外部ウェブサービスを呼び出すカスタムコードを挿入する <===
}
finally {
//問題を避けるためにスレッドの以前のクラスローダを復元する
currentThread.setContextClassLoader(threadClassLoader);
}.