2

我正在将 Spring Boot 应用程序转换为 Quarkus,作为概念证明。当我构建 Quarkus 应用程序并使用 Java 运行它时,它运行良好,但是当我尝试将它作为本机应用程序运行时,我在内部 sun 类 ( com.sun.xml.internal.ws.spi.ProviderImpl )上得到一个ClassNotFoundException,因为它在 Java 中运行,我希望 Native App 也能正常工作。

我在用着:

  • Quarkus 1.3.0.final
  • 使用 quay.io/quarkus/ubi-quarkus-native-image:19.3.1-java11
  • 其中有 openjdk version "11.0.6" 2020-01-14 OpenJDK Runtime Environment GraalVM CE 19.3.1 (build 11.0.6+9-jvmci-19.3-b07) OpenJDK 64-Bit Server VM GraalVM CE 19.3.1 (build 11.0.6+9-jvmci-19.3-b07, mixed mode, sharing)
  • 使用 gradle 构建
------------------------------------------------------------
Gradle 6.2
------------------------------------------------------------

Build time:   2020-02-17 08:32:01 UTC
Revision:     61d3320259a1a0d31519bf208eb13741679a742f

Kotlin:       1.3.61
Groovy:       2.5.8
Ant:          Apache Ant(TM) version 1.10.7 compiled on September 1 2019
JVM:          13.0.2 (AdoptOpenJDK 13.0.2+8)
OS:           Mac OS X 10.14.6 x86_64
  • 这个项目正在使用 WSDL(插件 no.nils.wsdl2java 0.12)
  • 我在 build.gradle 中添加了以下内容
   // wsdl2java JDK9+
   implementation 'com.sun.xml.bind:jaxb-xjc:2.3.0.1'
   implementation 'javax.xml.bind:jaxb-api:2.3.1'
   implementation 'javax.xml.ws:jaxws-api:2.3.1'
   implementation 'org.apache.cxf:cxf-rt-wsdl:3.2.7'
   implementation 'javax.jws:javax.jws-api:1.1'
//    implementation 'com.sun.xml.ws:rt:2.3.2'

gradle 构建命令是

./gradlew buildNative -i --stacktrace --docker-build=true -Dquarkus.native.builder-image=quay.io/quarkus/ubi-quarkus-native-image:19.3.1-java11

本机应用程序输出

我从ubi-quarkus-native-image中运行应用程序

[quarkus@79a141991f90 build]$./my-service-1.0.0-SNAPSHOT-runner 
__  ____  __  _____   ___  __ ____  ______ 
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \   
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/   
2020-03-25 21:44:21,365 INFO  [com.che.es.eng.HealthAggregator] (main) Initializing health checks for 3 engines!
2020-03-25 21:44:21,370 ERROR [com.che.es.eng.ExEngine] (taskScheduler-0) Error from Ex web services!: javax.xml.ws.WebServiceException: Provider com.sun.xml.internal.ws.spi.ProviderImpl not found
    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.newInstance(ServiceLoaderUtil.java:103)
    at javax.xml.ws.spi.FactoryFinder.find(FactoryFinder.java:112)
    at javax.xml.ws.spi.Provider.provider(Provider.java:96)
    at javax.xml.ws.Service.<init>(Service.java:112)
    at com.che.es.engine.wsdl.AddressValidationService.<init>(AddressValidationService.java:39)
    at com.che.es.engine.FedExHealthIndicator$FedExHealthCheckerTask.run(FedExHealthIndicator.java:70)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.lang.Thread.run(Thread.java:834)
    at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:497)
    at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:193)
Caused by: java.lang.ClassNotFoundException: com.sun.xml.internal.ws.spi.ProviderImpl
    at com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:60)
    at java.lang.ClassLoader.loadClass(Target_java_lang_ClassLoader.java:160)
    at javax.xml.ws.spi.ServiceLoaderUtil.nullSafeLoadClass(ServiceLoaderUtil.java:90)
    at javax.xml.ws.spi.ServiceLoaderUtil.safeLoadClass(ServiceLoaderUtil.java:123)
    at javax.xml.ws.spi.ServiceLoaderUtil.newInstance(ServiceLoaderUtil.java:101)
    ... 16 more
2020-03-25 21:44:21,377 INFO  [io.quarkus] (main) vs-service 1.0.0-SNAPSHOT (powered by Quarkus 1.3.0.Final) started in 0.191s. Listening on: http://0.0.0.0:8080

在同一个 docker 映像中使用 Java 启动时,它按预期工作

[quarkus@79a141991f90 build]$ java -jar my-service-1.0.0-SNAPSHOT-runner.jar 
__  ____  __  _____   ___  __ ____  ______ 
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \   
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/   
2020-03-25 21:53:00,789 INFO  [com.che.es.eng.HealthAggregator] (main) Initializing health checks for 3 engines!
2020-03-25 21:53:01,841 INFO  [io.quarkus] (main) vs-service 1.0.0-SNAPSHOT (powered by Quarkus 1.3.0.Final) started in 3.720s. Listening on: http://0.0.0.0:8080

我试过的

  • 谷歌:没有太多出现
  • 我确实发现一些提到添加com.sun.xml.ws:rt:2.3.2,但这会导致其他错误。

任何人有任何想法让这个工作?

4

4 回答 4

1

我遇到了这个问题Provider com.sun.xml.internal.stream.XMLInputFactoryImpl not found

它似乎已在 GraalVM 20 中解决,我可以通过设置以下内容application.properties来强制 Quarkus 针对 GraalVm 20.0.0 构建来解决此问题:

quarkus.native.builder-image=quay.io/quarkus/ubi-quarkus-native-image:20.0.0-java11
于 2020-06-05T14:33:12.737 回答
1

我决定用 CXF 而不是 JAX-WS 来实现它并且遇到了同样的问题。解决方案是在 META-INF/services 中定义 ProviderImpl,如下所示:

META-INF/services/javax.xml.ws.spi.Provider -> org.apache.cxf.jaxws.spi.ProviderImpl

此外,为了将此文件添加到本机图像,您需要将其作为附加资源提供:

1.在您的类路径中创建一个新文件 resources-config.json:

{
  "resources": [
    {
      "pattern": "META-INF/services/.*"
    }
  ]
}

2.将文件添加到quarkus maven插件中,以便它使用它来构建原生镜像

    <plugin>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-maven-plugin</artifactId>
        <version>${quarkus-plugin.version}</version>
        <executions>
            <execution>
                <goals>
                    <goal>native-image</goal>
                </goals>
                <configuration>
                    <reportErrorsAtRuntime>true</reportErrorsAtRuntime>
                    <additionalBuildArgs>-H:+AllowIncompleteClasspath,
                                        -H:ReflectionConfigurationFiles=reflection-config.json, 
-H:ResourceConfigurationFiles=resources-config.json
                    </additionalBuildArgs>
                    <enableHttpUrlHandler>true</enableHttpUrlHandler>
                </configuration>
            </execution>
        </executions>
    </plugin>
于 2020-06-10T14:07:20.210 回答
0

您不能使用 JVM 的内部类。实现类是“私有的”,永远不应该在依赖 JVM 实现的痛苦中使用。这是 JAVA 的基本原理之一。您应该找出为什么要使用实现类而不是相应的接口。然后找到一个不依赖于任何实现,而只依赖于 Java API 的解决方案。

于 2020-04-05T07:51:16.330 回答
0

添加这些安全和协议相关的 application.properties 为我解决了这个问题:

quarkus.native.additional-build-args=\
  -H:EnableURLProtocols=http\\,https,\
  --enable-all-security-services,\
  -H:+JNI

请参阅官方文档。

于 2021-02-23T13:20:10.543 回答