OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.67k stars 6.54k forks source link

[BUG][Quarkus] REST-client interfaces in Quarkus sends empty payloads when used with GraalVM native compilation #15141

Open SaddexProductions opened 1 year ago

SaddexProductions commented 1 year ago
Description

I have a Quarkus application which has three modules: api, app and ext. api is a module that contains an Openapi file which specifies the API for the application itself and which Openapi-generator uses to generate interfaces which are implemented within app. ext on the other hand contains Openapi contracts for external APIs which my service connects to, and generates interfaces that are injected as REST clients in app.

@ApplicationScoped
@Slf4j
public class CustomerFacade {

  @Inject
  @RestClient
  RestClient1 restclient1;

  @Inject
  @RestClient
  RestClient2 restclient2;

  public String getCustomerId(String id) {

     var request = orc.acme.ext.modell.<RETRACTED>.Input.builder()
                .dto(List.of(DTO.builder().id(id).category(1L).build())).build();
     log.debug(((Integer) request.getDTO().size()).toString());
     log.debug(request.getDTO().get(0).toString());

     var response = restclient1.fetch("", "88880001", "", 0, request);
     return onlyOne(response.getServiceReturnValue()).getCustomerId();
  }
  //...
}

This works without issues in a jar build. However, with a native build, the issue seems to be that the request body becomes empty. I've tried debugging it using the above log statements, as well as container logs, which all verified that the connection works as expected, the headers (for example the number 88880001) are properly attached and the request body POJO is properly generated before the REST client gets it. However, what is actually sent by the REST Client is an empty {}. We also don't use custom additional application.properties' files in this application, which otherwise could be a source of frustration but one that also has been migitated since then.

I tried adding these lines in application.properties:

quarkus.native.enable-http-url-handler=true
quarkus.native.enable-https-url-handler=true

Did not solve the issue. I also tried adding *serializableModel: "true" in configOptions, also did not work. Same with

additionalModelTypeAnnotations: "@javax.enterprise.context.ApplicationScoped"

which also did not work.

openapi-generator version

Version 6.1.0 initially. Incremented to 6.4.0 which is the latest version my organisation provides. Did not solve the issue.

OpenAPI declaration file content or url

Only the body has been included because the scope of the issue seems to be limited to it, and the fields have been changed due to the actual APIs being confidential.

components:
  schemas:
    Input:
      example:
        lookup:
        - customerid: customerid
          period:
            end: end
            start: start
            updated:
              source: 1
              timestamp: timestamp
          category: 0
          entity:
            id: 0
            identity: identity
          id: id
        - customerid: customerid
          period:
            end: end
            start: start
            updated:
              source: 1
              timestamp: timestamp
          category: 0
          entity:
            id: 0
            identity: identity
          id: id
Generation Details

In build.gradle for the ext module:

fileTree("${project.projectDir}/contract").matching { exclude "\\.*" }.each { file ->
    def api = file.getName().substring(0, file.getName().lastIndexOf("."))
    def taskName = "openApiGenerate${api.substring(0, 1).toUpperCase()}${api.substring(1)}"
    def subProject = "${project.properties.get("group")}.extern.ext"

    tasks.create(taskName, GenerateTask.class) {
        generatorName = "jaxrs-spec"
        inputSpec = file.getPath()
        outputDir = "$project.buildDir/generated"
        apiPackage = "${subProject}.resurser"
        modelPackage = "${subProject}.modell.${api}"
        configOptions = [
                // additionalModelTypeAnnotations: "@javax.enterprise.context.ApplicationScoped",
                booleanGetterPrefix  : "is",
                dateLibrary          : "java8",
                generateBuilders     : "true",
                interfaceOnly        : "true",
                library              : "quarkus",
                returnResponse       : "false",
                // Prevent dependency on swagger in API
                useSwaggerAnnotations: "false",
                useTags              : "true",
                useBeanValidation    : "true",
        ]
        globalProperties = [
                apiTests  : "false",
                modelTests: "false"
        ]
    }

    compileJava.dependsOn(taskName)
}
Steps to reproduce

Create a multi-module Quarkus project that uses Openapi-generator to generate REST client interfaces. Inject these interfaces in an @ApplicationScoped bean, and create a POST request, maybe using the body specification above. Use builders. Build the application using GraalVM and then trigger code that uses the REST client generated by Openapi-generator.

Related issues/PRs
Suggest a fix
SaddexProductions commented 1 year ago

Additional details:

Java version: 17.04 GraalVM version: 22.2.0 Quarkus version: 2.15.0.Final