2
votes

I am converting a Spring Boot application to Quarkus, as a proof of concept. When I build the Quarkus app and run it with Java it runs fine, but when I try to run it as a native application I get a ClassNotFoundException on an internal sun class (com.sun.xml.internal.ws.spi.ProviderImpl), since it runs in Java I would expect the Native App to work as well.

I'm using:

  • Quarkus 1.3.0.final
  • Using quay.io/quarkus/ubi-quarkus-native-image:19.3.1-java11
  • Which has 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)
  • Building with 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
  • This project is using WSDL (plugin no.nils.wsdl2java 0.12)
  • And I added the following in 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'

The gradle build command is

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

Native App Output

I run the application from within the 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

When started with Java in the same docker image it works as expected

[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

What I tried

  • Google: Not much comes up
  • I did find some mention of adding com.sun.xml.ws:rt:2.3.2, but this causes other errors.

Anyone have any thoughts on getting this to work?

4
It seems you're trying to use JAX-WS, but that isn't supported in Quarkus yet. There will have to be an extension for it to work in native. There's a feature request for CXF support: github.com/quarkusio/quarkus/issues/4005 - Ladicek
hi, any update on this topic? I am facing exactly the same problem. We have a REST Api which consumes a SOAP Service using jaxws. Everything work on the JVM Image but with the Native image I am getting the "ClassNotFoundException: com.sun.xml.internal.ws.spi.ProviderImpl". - Iván Pérez
Check this stackoverflow.com/a/61801701/3701228 maybe it will work if you add that class explicitly via reflection-config.json - Gas

4 Answers

1
votes

I was having this issue with Provider com.sun.xml.internal.stream.XMLInputFactoryImpl not found.

It seems to have been resolved in GraalVM 20, and I was able to fix this by settng the following in application.properties to force Quarkus to build against GraalVm 20.0.0:

quarkus.native.builder-image=quay.io/quarkus/ubi-quarkus-native-image:20.0.0-java11
1
votes

I decided to implement it with CXF instead of JAX-WS and had the same problem. The solution was to define the ProviderImpl inside META-INF/services as follows:

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

Furthermore, in order to add this file to the native image, you need to provide it as additionally resource:

1.Make a new file resources-config.json within your classpath:

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

2.Add the file to the quarkus maven plugin, so that it uses it to build the native image

    <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>
0
votes

You cannot use internal classes of JVMs. The implementation classes are "private" and should never be used under pain of being dependent on the implementation of the JVM. This is one of the fundamentals of JAVA. You should find out why you are using an implementation class instead of the corresponding interface. And then find a solution that does not depend on any implementation, but only on the Java API.

0
votes

Adding these security and protocol related application.properties solved the problem for me:

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

See the official documentation.