3

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?

Jim M.
  • 909
  • 1
  • 12
  • 29
  • 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: https://github.com/quarkusio/quarkus/issues/4005 – Ladicek Mar 26 '20 at 07:31
  • 2
    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 May 20 '20 at 12:37
  • Check this https://stackoverflow.com/a/61801701/3701228 maybe it will work if you add that class explicitly via `reflection-config.json` – Gas Jun 06 '20 at 10:02

4 Answers4

1

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
Adam Millerchip
  • 20,844
  • 5
  • 51
  • 74
1

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

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.

Sekaijin
  • 107
  • 1
  • 6
  • I am not using the internal class, it is being used by JAX-WS.... – Jim M. Apr 06 '20 at 13:04
  • You need to find out why your code is loading com.sun.xml.internal.ws.spi.ProviderImpl From my memory this class no longer exists in the JDK since version 11 A+JYT – Sekaijin May 22 '20 at 18:25
0

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.

Péter Veres
  • 955
  • 1
  • 10
  • 25