quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.87k stars 2.71k forks source link

Custom Converter is not available during Maven-Build #36346

Closed ZeTo12 closed 1 year ago

ZeTo12 commented 1 year ago

Describe the bug

I have created a Custom Configuration Converter according to the documentation in https://quarkus.io/guides/config-extending-support#custom-converter

When building the application using maven, I get the following error message:

[INFO] Scanning for projects... [INFO] [INFO] ----------------------< my-groupId:my-artifactId >---------------------- [INFO] Building my-artifactId 1.0.0-SNAPSHOT [INFO] from pom.xml [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- resources:3.3.1:resources (default-resources) @ my-artifactId --- [INFO] Copying 3 resources from src\main\resources to target\classes [INFO] [INFO] --- quarkus:3.4.2:generate-code (default) @ my-artifactId --- [WARNING] [io.quarkus.deployment.CodeGenerator] The following services are not (yet) available and will be disabled during configuration initialization at the current build phase: my.groupId.MyConfigConverter [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] Total time: 7.791 s [INFO] Finished at: 2023-10-09T09:29:52+02:00 [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal io.quarkus.platform:quarkus-maven-plugin:3.4.2:generate-code (default) on project my-artifactId: Quarkus code generation phase has failed: InvocationTargetException: org.eclipse.microprofile.config.spi.Converter: Provider my.groupId.MyConfigConverter not found -> [Help 1] [ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. [ERROR] Re-run Maven using the -X switch to enable full debug logging. [ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

A REST resource and a corresponding test were created with the Quckstart sample. When I run the test, the Custom Config Converter is run. The test works from the IDE (IntelliJ IDEA). If I build the application with maven, I get the above output.

The example with the custom converter still worked with Quarkus version 3.2.4.Final. The application could be built with 3.2.4.Final and maven.

With the current version 3.4.2 the maven build fails.

Expected behavior

The example with the Custom Converter, to be found under https://quarkus.io/guides/config-extending-support#custom-converter, should work with the current Quarkus version 3.4.2.

Actual behavior

No response

How to Reproduce?

Output of uname -a or ver

No response

Output of java -version

No response

GraalVM version (if different from Java)

No response

Quarkus version or git rev

3.4.2

Build tool (ie. output of mvnw --version or gradlew --version)

maven

Additional information

No response

quarkus-bot[bot] commented 1 year ago

/cc @quarkusio/devtools (maven)

aloubyansky commented 1 year ago

There must be something more in the project to make it fail. Does the project include a source code generating extension? Does that code generator read the config?

ZeTo12 commented 1 year ago

Thank you for pointing that out. It is indeed the case. I had the Quarkus CXF extension in the Maven POM. If I take CXF out, the Maven build works.

<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>my-groupId</groupId>
  <artifactId>my-artifactId</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <properties>
    <compiler-plugin.version>3.11.0</compiler-plugin.version>
    <maven.compiler.release>17</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.4.2</quarkus.platform.version>
    <skipITs>true</skipITs>
    <surefire-plugin.version>3.1.2</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>
<!--      <dependency>
        <groupId>${quarkus.platform.group-id}</groupId>
        <artifactId>quarkus-cxf-bom</artifactId>
        <version>${quarkus.platform.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>-->
    </dependencies>
  </dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-arc</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy-reactive</artifactId>
    </dependency>
<!--    <dependency>
      <groupId>io.quarkiverse.cxf</groupId>
      <artifactId>quarkus-cxf</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>
  </dependencies>
  <build>
    <plugins>
      ...
   </plugins>
  </build>
   ...
</project>

What do I have to do to make the Maven build work with the CXF extension? It still worked in version 3.2.4-Final.

aloubyansky commented 1 year ago

@ZeTo12 while it used to work, this kind of project configuration is flawed. Here is what happens.

The application module includes classes that are required for configuration initialization. The CXF extension generates source code and so has to do that before the compile phase. At the same time, the application configuration has to be provided to the source code generator. Given that it happens before the compile phase, the configuration related classes in the application module haven't been compiled yet and aren't available, which leads to configuration initialization failure.

The reason it used to work before was that the configuration initialization in the pre-compile phase wasn't complete and we had multiple bug reports about that. It did make sense to fix it, although unfortunately now it breaks your use-case.

In this case, the recommended approach would be to extract the config related classes into a separate module and make the application module depend on it.

ZeTo12 commented 1 year ago

Thank you for the analysis Alexey.

I tried your suggestion right away. I made a multi-module Maven project. One sub-module was the Custom Configuration Module. Another one was the Quarkus Module. The Quarkus Module referenced the Custom Configuration Module. It works.

But I have to say that it feels a bit strange to make a separate module for a custom configuration.

I now see this as a workaround. How will this be handled now? Will the implementation be changed again? So that a separate module is no longer necessary at some point? Or will it remain with the workaround with the separate module?

If we stay with the workaround? How can we document this in any way?

I think this issue has been solved. There is a working workaround.

aloubyansky commented 1 year ago

As long as we have config classes in the application module, we can't have a fully initialized configuration before the compile phase. It's a chicken-egg problem. We could probably configure multiple executions of compile and run the generate-code goals in between but I am not sure it's worth it, tbh.

This could certainly be documented, such as "in case in application includes source code generating extensions, such as CXF, gRPC, Avro, etc, MP Config related API implementation classes should be extracted to their own module and added as dependencies of the application module to make sure their classes are available during config initialization in the source code generation phase."