quarkiverse / quarkus-cxf

Quarkus CXF Extension to support SOAP based web services.
Apache License 2.0
76 stars 60 forks source link

WSDL To Java : generated class reflection problem in native compilation mode #1221

Closed rayanrbn closed 7 months ago

rayanrbn commented 7 months ago

Hi,

I'm trying to get a SOAP Client working in native quarkus application, the build works fine, I can run the application without any problem. But when I call my resource that access to the generated SOAP client I get :

org.graalvm.nativeimage.MissingReflectionRegistrationError: The program tried to reflectively access the proxy class inheriting [fr.myservice.webservice.MyServiceSoap, jakarta.xml.ws.BindingProvider, java.io.Closeable, org.apache.cxf.endpoint.Client] without it being registered for runtime reflection. Add [fr.myservice.webservice.MyServiceSoap, jakarta.xml.ws.BindingProvider, java.io.Closeable, org.apache.cxf.endpoint.Client] to the dynamic-proxy metadata to solve this problem.

I generate the SOAP client from a .wsdl file that I specify in the application.properties file. I was expecting Quarkus CXF to handle all the reflection stuff for native compilation.

If anyone has any suggestions I will be pleased to hear. Thanks!

ppalaga commented 7 months ago

Would you please share your pom.xml (after removing what you do not want to show to the whole world)?

rayanrbn commented 7 months ago

Would you please share your pom.xml (after removing what you do not want to show to the whole world)? Thanks for the fast reply!

Sure, here it is:

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>fr.myservice</groupId>
  <artifactId>servicename</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <properties>
    <compiler-plugin.version>3.12.1</compiler-plugin.version>
    <maven.compiler.release>21</maven.compiler.release>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
    <quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
    <quarkus.platform.version>3.7.1</quarkus.platform.version>
    <skipITs>true</skipITs>
    <surefire-plugin.version>3.2.3</surefire-plugin.version>
  </properties>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>${quarkus.platform.group-id}</groupId>
        <artifactId>${quarkus.platform.artifact-id}</artifactId>
        <version>${quarkus.platform.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-rest-client-reactive-jackson</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-cache</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-hibernate-orm-panache</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-hibernate-orm</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy-reactive-jackson</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-jdbc-mssql</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy-reactive</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-arc</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-jdbc-postgresql</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-junit5</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>io.rest-assured</groupId>
      <artifactId>rest-assured</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-flyway</artifactId>
    </dependency>
    <dependency>
      <groupId>com.github.joniles</groupId>
      <artifactId>rtfparserkit</artifactId>
      <version>1.16.0</version>
    </dependency>
    <dependency>
      <groupId>io.quarkiverse.cxf</groupId>
      <artifactId>quarkus-cxf</artifactId>
      <version>2.4.1</version>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>${quarkus.platform.group-id}</groupId>
        <artifactId>quarkus-maven-plugin</artifactId>
        <version>${quarkus.platform.version}</version>
        <extensions>true</extensions>
        <executions>
          <execution>
            <goals>
              <goal>build</goal>
              <goal>generate-code</goal>
              <goal>generate-code-tests</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${compiler-plugin.version}</version>
        <configuration>
          <compilerArgs>
            <arg>-parameters</arg>
          </compilerArgs>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${surefire-plugin.version}</version>
        <configuration>
          <systemPropertyVariables>
            <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
            <maven.home>${maven.home}</maven.home>
          </systemPropertyVariables>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>${surefire-plugin.version}</version>
        <executions>
          <execution>
            <goals>
              <goal>integration-test</goal>
              <goal>verify</goal>
            </goals>
            <configuration>
              <systemPropertyVariables>
                <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
                <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
                <maven.home>${maven.home}</maven.home>
              </systemPropertyVariables>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  <profiles>
    <profile>
      <id>native</id>
      <activation>
        <property>
          <name>native</name>
        </property>
      </activation>
      <properties>
        <skipITs>false</skipITs>
        <quarkus.package.type>native</quarkus.package.type>
      </properties>
    </profile>
  </profiles>
</project>
ppalaga commented 7 months ago

You need to add quarkus-cxf-bom as documented around here

  <dependencyManagement>
      ...
      <dependency>
        <groupId>${quarkus.platform.group-id}</groupId>
        <artifactId>quarkus-cxf-bom</artifactId>
        <version>${quarkus.platform.version}</version>
        <type>pom</type>
        <scope>import</scope>

and remove the version from the quarkus-cxf dependency.

rayanrbn commented 7 months ago

Thanks, I forgot to add that, indeed.

I did a quarkus ext remove io.quarkiverse.cxf:quarkus-cxf then quarkus add io.quarkiverse.cxf:quarkus-cxf, so it indeed added me the BOM and removed the version in the CXF dependency. But I still get the same error.

The new pom.xml if needed :

pom.xml ```xml 4.0.0 fr.myservice servicename 1.0.0-SNAPSHOT 3.12.1 21 UTF-8 UTF-8 quarkus-bom io.quarkus.platform 3.7.1 true 3.2.3 ${quarkus.platform.group-id} ${quarkus.platform.artifact-id} ${quarkus.platform.version} pom import ${quarkus.platform.group-id} quarkus-cxf-bom ${quarkus.platform.version} pom import io.quarkus quarkus-rest-client-reactive-jackson io.quarkus quarkus-cache io.quarkus quarkus-hibernate-orm-panache io.quarkus quarkus-hibernate-orm io.quarkus quarkus-resteasy-reactive-jackson io.quarkus quarkus-jdbc-mssql io.quarkus quarkus-resteasy-reactive io.quarkus quarkus-arc io.quarkus quarkus-jdbc-postgresql io.quarkiverse.cxf quarkus-cxf io.quarkus quarkus-junit5 test io.rest-assured rest-assured test io.quarkus quarkus-flyway com.github.joniles rtfparserkit 1.16.0 ${quarkus.platform.group-id} quarkus-maven-plugin ${quarkus.platform.version} true build generate-code generate-code-tests maven-compiler-plugin ${compiler-plugin.version} -parameters maven-surefire-plugin ${surefire-plugin.version} org.jboss.logmanager.LogManager ${maven.home} maven-failsafe-plugin ${surefire-plugin.version} integration-test verify ${project.build.directory}/${project.build.finalName}-runner org.jboss.logmanager.LogManager ${maven.home} native native false native ```

Do you have any other hints or ideas?

Thanks again!

ppalaga commented 7 months ago

OK, I see, you perhaps create the client via Service.create(serviceUrl, qName).getPort(clazz). ? - Indeed, that won't work in native mode. Please follow the user guide https://docs.quarkiverse.io/quarkus-cxf/dev/user-guide/first-soap-client.html

rayanrbn commented 7 months ago

The client is injected in a Service and created by a producer class:

// File: [ServiceName]SoapProducer.java
@ApplicationScoped
public class ServiceNameServiceSoapProducer {
    private final Duration timeout;

    public ServiceNameServiceSoapProducer(@ConfigProperty(name = "myservice.serviceName.webservice.timeout", defaultValue = "30000") Integer timeout) {
        this.timeout = Duration.ofMillis(timeout);
    }

    @Produces
    @ApplicationScoped
    public ServiceNameServiceSoap getServiceNameServiceSoap() {
        HTTPConduitConfigurer httpConduitConfigurer = (s, s1, httpConduit) -> {
            HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();

            httpClientPolicy.setConnectionTimeout(timeout.toMillis());
            httpClientPolicy.setReceiveTimeout(timeout.toMillis());

            httpConduit.setClient(httpClientPolicy);
        };

        final Bus bus = BusFactory.getDefaultBus();
        bus.setExtension(httpConduitConfigurer, HTTPConduitConfigurer.class);

        return new ServiceNameService().getServiceNameServiceSoap();
    }
}

// File: [ServiceName]WebServiceImpl.java
@ApplicationScoped
public class ServiceNameWebServiceImpl implements ServiceNameWebService {
    // ...
    private final ServiceNameServiceSoap serviceNameServiceSoap;

    @Inject
    public ServiceNameWebServiceImpl(ServiceNameServiceSoap serviceNameServiceSoap) {
        this.serviceNameServiceSoap = serviceNameServiceSoap;
    }

    /**
     * ...
     */
}

Maybe the producer is what cause the problem? Or do I need some sort of annotation like @CXFClient(...) when injecting the client?

Thanks a lot for the responses and the help!

ppalaga commented 7 months ago

do I need some sort of annotation like @CXFClient(...) when injecting the client?

Exactly. That's the only way supposed to work in native Mode.

ppalaga commented 7 months ago

The stuff you do via custom HTTPConduitConfigurer can also be configured in application properties via quarkus.cxf.client.myClient.connection-timeout and quarkus.cxf.client.myClient.receive-timeout - see https://docs.quarkiverse.io/quarkus-cxf/dev/reference/extensions/quarkus-cxf.html#quarkus-cxf_quarkus-cxf-client-clients-connection-timeout

rayanrbn commented 7 months ago

Uh, I feel so dumb, it was in front of me in the documentation..

I'm sorry for wasting you time, but also thankful you took some of that time to help me!

The stuff you do via custom HTTPConduitConfigurer can also be configured in application properties via quarkus.cxf.client.myClient.connection-timeout and quarkus.cxf.client.myClient.receive-timeout - see https://docs.quarkiverse.io/quarkus-cxf/dev/reference/extensions/quarkus-cxf.html#quarkus-cxf_quarkus-cxf-client-clients-connection-timeout

That's definitely interesting too.

Thank you so much! Have a nice day, best regards.

ppalaga commented 7 months ago

I am happy I could help :)