Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG][JAXRS-SPEC] Schema Mapping Produces Compilation Error; Type Parameter Annotated with @Valid #20377

Open
5 of 6 tasks
mikewacker opened this issue Dec 26, 2024 · 1 comment

Comments

@mikewacker
Copy link

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

The issue happens when an object has a property of type array, and you use a schema mapping for the array type:

    GetItemsResponse:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/Item'
      required:
        - items

--schema-mappings Item=org.example.Item

Actual Output: Here's the line that doesn't compile:

  @NotNull @Valid public List<@Valid org.example.Item> getItems() {

Note: @Valid is a Jakarta annotation here.

Expected Output: The type parameter should not be annotated with @Valid.

Impact: I have a build workflow where I generate Java sources from OpenAPI YAML, and then compile the generated sources. The impact is severe when the code that is generated doesn't compile.

openapi-generator version

7.10.0

OpenAPI declaration file content or url

I've produced a simpler example that reproduces the problem:

openapi: 3.0.0

info:
  title: Test API
  version: 1.0.0

paths:
  /get-items:
    get:
      operationId: getItems
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetItemsResponse'

components:
  schemas:
    GetItemsResponse:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/Item'
      required:
        - items
    Item:
      type: string

The idea here is that we can use a scheme mapping for Item, but it will default to a string without the mapping.

Generation Details

I'm using the Gradle plugin to generate JAX-RS interfaces, and then I compile the sources. I do use a schema mapping for one type. Here is a simpler build file that reproduces the problem.

build.gradle.kts

plugins {
    `java-library`
    id("org.openapi.generator") version "7.10.0"
}

fun projectFilePath(relativePath: String): Provider<String> =
    layout.projectDirectory.file(providers.provider { relativePath }).map { it.asFile.absolutePath }

fun buildDirPath(relativePath: String): Provider<String> =
    layout.buildDirectory.dir(relativePath).map { it.asFile.absolutePath }

// Validate the OpenAPI YAML.
openApiValidate {
    inputSpec = projectFilePath("src/main/resources/api.yaml")
}

// Generate JAX-RS server interfaces from the OpenAPI YAML.
openApiGenerate {
    generatorName = "jaxrs-spec"
    inputSpec = projectFilePath("src/main/resources/api.yaml")
    schemaMappings = mapOf("Item" to "org.example.Item")
    outputDir = buildDirPath("generated/sources/openApi/java/main")

    // Generate interfaces.
    configOptions = mapOf(
        "interfaceOnly" to "true",
        "sourceFolder" to "",
        "useJakartaEe" to "true",
        "useSwaggerAnnotations" to "false",
    )

    // Generate only the apis and models. Don't generate the invokers or other supporting files.
    apiPackage = "org.example"
    modelPackage = "org.example"
    globalProperties = mapOf(
        "apis" to "",
        "models" to "",
    )
}

// Compile the Java sources that are generated from the OpenAPI YAML.
sourceSets {
    main {
        java {
            srcDir(tasks.named("openApiGenerate"))
        }
    }
}

repositories {
    mavenCentral()
}

dependencies {
    api(libs.jackson.annotations)
    api(libs.jakartaAnnotation.api)
    api(libs.jakartaValidation.api)
    api(libs.jaxRs.api)
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}
Steps to reproduce
  • Download and extract archive.zip, and run ./gradlew build.
  • If you remove the schemaMappings line from build.gradle.kts, it will build successfully.
Related issues/PRs
Suggest a fix

The Jakarta @Valid annotation should not be used for a type parameter.

@mikewacker
Copy link
Author

I did find a workaround: use a Gradle Copy task to fix the compilation errors. It has a filter arg which lets you modify the lines you're copying. You can generate the files into a tmp folder, and then copy (and fix) it from said tmp folder.

// Generate JAX-RS server interfaces from the OpenAPI YAML.
openApiGenerate {
    generatorName = "jaxrs-spec"
    inputSpec = projectFilePath("src/main/resources/api.yaml")
    schemaMappings = mapOf("Item" to "org.example.Item")
    outputDir = buildDirPath("tmp/openApi")

    // Generate interfaces.
    configOptions = mapOf(
        "interfaceOnly" to "true",
        "sourceFolder" to "",
        "useJakartaEe" to "true",
        "useSwaggerAnnotations" to "false",
    )

    // Generate only the apis and models. Don't generate the invokers or other supporting files.
    apiPackage = "org.example"
    modelPackage = "org.example"
    globalProperties = mapOf(
        "apis" to "",
        "models" to "",
    )
}

tasks.register<Copy>("fixCompilationErrors") {
    from(tasks.named("openApiGenerate"))
    into(layout.buildDirectory.dir("generated/sources/openApi/java/main"))
    filter { it.replace("<@Valid ", "<") }
}

// Compile the Java sources that are generated from the OpenAPI YAML.
sourceSets {
    main {
        java {
            srcDir(tasks.named("fixCompilationErrors"))
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant