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][JAVA] JsonNullable<?> is not generated for property define as nullable:true #17873

Closed robertop87 closed 8 months ago

robertop87 commented 8 months ago

Bug Report Checklist

Description

I've create this repository as example https://github.com/robertop87/opengen

The problem is that the generator (gradle plugin 7.3.0) is not generating JsonNullable<?> for properties defined as nullable: true

Update 2: According docs, enabling x-is-jackson-optional-nullable extension should generate the expected code, but it has no any effect in generation.

Update 1: Based on community suggestion, I changed the generatorName from java to spring, then the JsonNullable was generated correctly BUT the generated code is a spring server application, which is not the goal for this case. The goal is to generate a JAVA client.

openapi-generator version

id "org.openapi.generator" version "7.3.0"

OpenAPI declaration file content or url

https://github.com/robertop87/opengen/blob/main/swagger.yml

Generation Details

Just using the mentioned gradle plugin, steps to generate are in the repository https://github.com/robertop87/opengen

./gradlew clean assemble

Steps to reproduce

Generate the Pet.java class

Related issues/PRs

https://github.com/OpenAPITools/openapi-generator/issues/14765

MelleD commented 8 months ago

Did you enable openApiNullable https://openapi-generator.tech/docs/generators/spring/

tofi86 commented 8 months ago

I also just stumbled upon this issue when testing v7.3.0 – but I tested with the maven plugin.

@MelleD openApiNullable is documented to be enabled by default 🤷

MelleD commented 8 months ago

Hey @tofi86 I tried it with:

    <groupId>org.openapitools</groupId>
    <artifactId>openapi-generator-maven-plugin</artifactId>
    <version>7.3.0</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <inputSpec>
                    ${project.basedir}/swagger.yml
                </inputSpec>
                <generatorName>spring</generatorName>
                <apiPackage>test</apiPackage>
                <modelPackage>test</modelPackage>
            </configuration>
        </execution>
    </executions>

and works


public class Pet {

  private Long id;

  private String name;

  private JsonNullable<String> tag = JsonNullable.<String>undefined();

  public Pet() {
    super();
  }

So not sure what maven settings you are using

MelleD commented 8 months ago

@robertop87 not familiar with gradle but you have to use the spring generator and not the java generator. generatorName.set("java") looks wrong

I linked the documentation to the spring generator above

tofi86 commented 8 months ago

@MelleD damn, that was the result of the cli generator I tested – and for some reason I had set it to the java generator as well but meant to test spring 🙈 Sorry...

robertop87 commented 8 months ago

Awesome. I got the expected behavior with the next changes (build.gradle).

https://github.com/robertop87/opengen/commit/540a8dd4f6e51f4b95eff452f63e32a10dc50a48

I'll double check if it's working as expected in a real project and I'll back to close this issue. Thank you.

robertop87 commented 8 months ago

Hello @MelleD ,

I just notice that using generatorName = spring, it's generating a full serve application, not just a java client.

In that context I think this is still a bug, I mean JsonNullable is not being generated for java client.

I updated my repo in this commit: https://github.com/robertop87/opengen/commit/b4077778561bdd0cc1adc8018d497065a38798f9

CC: @tofi86

MelleD commented 8 months ago

@robertop87 Iam using the spring generator with open feign clients and there is no full application it’s DTO + clients. Iam not aware with the Java generator and which library the Java client is using (there is also more than library) see documentation . Not sure if every library generator supports JsonNullable because it’s depending on Jackson

Here are the templates for the Java client I see no JsonNullable https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources/Java/pojo.mustache

robertop87 commented 8 months ago

@MelleD

I understood, so in short:

currently openapi-generator does not support the generation of java client using JsonNullable<?> for "nullable: true" defined properties.

is that correct?

Update: In the provided link I saw the next lines where JsonNullable is present: image

But maybe I'm wrong because first time I read mustache code.

CC @tofi86

MelleD commented 8 months ago

How I said iam not sure, iam not using this generator: https://openapi-generator.tech/docs/generators/java/

You see there are lot of library which you can select. Maybe one of this supports JsonNullable

Iam using this generator with spring and open feign. There it is supported. https://openapi-generator.tech/docs/generators/spring

You can generate client + dto/models with open feign without a entire application https://docs.spring.io/spring-cloud-openfeign/reference/index.html

MelleD commented 8 months ago

Just checked out the source code and made a small text search. Looks like there should be something in place for java...

Bildschirmfoto 2024-02-16 um 20 33 44
tofi86 commented 8 months ago

@robertop87 I guess you're right. That's what I saw as well when accidentally using the java generator yesterday. No JsonNullable being generated - although openApiNullable is mentioned on the java generator docs page as being supported. Seems as if that's just not correct.

MelleD commented 8 months ago

Sure I think you have to enable this vendor extension then it should work

  {{#vendorExtensions.x-is-jackson-optional-nullable}}
  {{#isContainer}}
  private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined();
  {{/isContainer}}
  {{^isContainer}}
  private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}};
  {{/isContainer}}
  {{/vendorExtensions.x-is-jackson-optional-nullable}}

Here: https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources/Java/pojo.mustache#L86

But looks like this vendor extension is missing here in the documentation: https://openapi-generator.tech/docs/generators/java/

So this is maybe the bug here, that the docu is outdated.

robertop87 commented 8 months ago

@MelleD thanks for your time, I'm trying to enable the extension in my swagger.yml and also in swagger.json files, for example:

image

But it looks like has no effect to generate the JsonNullable types, so maybe I'm doing something wrong.

I following this guide: https://docs.readme.com/main/docs/openapi-extensions

One question more, does the vendor extension needs to be declared somehow in params for openapi-generator?

MelleD commented 8 months ago

I have no idea.

The x-field-extra-annotation is working. The jackson not

 tag:
          x-field-extra-annotation: "@javax.persistence.Id"
MelleD commented 8 months ago

Maybe you have to debug: https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java#L2475

robertop87 commented 8 months ago

@MelleD

When debugging I noticed that JsonNullable is working fine, because the generator's library is configured as WEBCLIENT.

Additionally note: x-is-jackson-optional-nullable was not needed in the configuration.

So I configured my generator like this:

tasks.register('generateClient', GenerateTask) {
    generatorName.set("java")
    library.set("webclient") // only with webclient the JsonNullable is generated properly
    inputSpec.set(swaggerFile.toString())
    outputDir.set(swaggerOutputDir)
    configOptions.set([
            dateLibrary: "java8",
            useJakartaEe: "true",
            openApiNullable: "true" // This is enabled by default
    ])
}

As result the JsonNullable were generated properly.

But, I'll test a bit more in client side if it's working as expected.

robertop87 commented 8 months ago

Hello @MelleD I confirmed that the bug is only present when library configuration is: okhttp-gson or microprofile so I reported in a new issue https://github.com/OpenAPITools/openapi-generator/issues/17919

So I'm closing this issue. 17873