Skip to content

[Generator][WIP]Extract schema name for requestBody when using oneOf #8423

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

Conversation

hugo-ma-alves
Copy link
Contributor

Hello

I was having some difficulties generating the java (feign) client when the requestBody included the oneOf directive. Let me try to illustrate with an example using the following spec.

openapi: 3.0.1
info:
  title: Sample OneOf
  description: Sample OneOf
  version: v1
servers:
  - url: 'http://localhost:8080'
    description: Generated server url
paths:
  /pet:
     post:
      tags:
        - creation
      summary: Create a new Pet
      operationId: create
      parameters:
        - name: Accept-Language
          in: header
          description: Language
          schema:
            type: string
            enum:
              - FR
              - DE
              - EN
      requestBody:
        content:
          application/json:
            schema:
              oneOf:
              - $ref: '#/components/schemas/Cat'
              - $ref: '#/components/schemas/Dog'
              - $ref: '#/components/schemas/Lizard'
              x-one-of-name: Pet
      responses:
        '201':
          description: The was created
components:
  schemas:
    Pet:
      type: object
      required:
      - petType
      properties:
        petType:
          type: string
      discriminator:
        propertyName: petType
        mapping:
          dog: Dog
          cat: Cat
          lizzard: Lizzard
    Cat:
      allOf:
      - $ref: '#/components/schemas/Pet'
      - type: object
        properties:
          name:
            type: string
    Dog:
      allOf:
      - $ref: '#/components/schemas/Pet'
      - type: object
        properties:
          bark:
            type: string
    Lizard:
      allOf:
      - $ref: '#/components/schemas/Pet'
      - type: object
        properties:
          lovesRocks:
            type: boolean

And to generate the client I use the following command:

generate -i "sample.yml" -g java -o pet-client --additional-properties=library=feign

So for the first try I used the code on the master branch and I got the following API class:

public interface CreationApi extends ApiClient.Api {

  /**
   * Create a new Pet
   * 
   * @param acceptLanguage Language (optional)
   * @param UNKNOWN_BASE_TYPE  (optional)
   */
  @RequestLine("POST /pet")
  @Headers({
    "Content-Type: application/json",
    "Accept: application/json",
    "Accept-Language: {acceptLanguage}"
  })
  void create(@Param("acceptLanguage") String acceptLanguage, UNKNOWN_BASE_TYPE UNKNOWN_BASE_TYPE);
}

The generator couldn't extract the correct type that encapsulates the subtypes of the Pet, so it uses the default value "UNKNOWN_BASE_TYPE.
I tracked this value to the line

LOGGER.warn("codegenModel is null. Default to UNKNOWN_BASE_TYPE");
. By default if it doesn't have another value it uses this one.
Not sure if it is related with this ticket #7256

Then I tried to use the extension x-one-of-name to manually define the model name to "Pet". This type is correctly created as a Java class from where the subtypes extend. And I got the same result.

I searched the code and found the function that parses the requestBody:

if (StringUtils.isNotBlank(schema.get$ref())) {
name = ModelUtils.getSimpleRef(schema.get$ref());
}
schema = ModelUtils.getReferencedSchema(this.openAPI, schema);

It looks to me that it expects a $ref for the requestBody schema and it doesn't takes in consideration that it can contain a oneOf ( I believe it is called inline schema? not sure about the naming). I then ran the generator with the change included in this PR and I got the following API.

public interface CreationApi extends ApiClient.Api {
  /**
   * Create a new Pet
   * 
   * @param acceptLanguage Language (optional)
   * @param pet  (optional)
   */
  @RequestLine("POST /pet")
  @Headers({
    "Content-Type: application/json",
    "Accept: application/json",
    "Accept-Language: {acceptLanguage}"
  })
  void create(@Param("acceptLanguage") String acceptLanguage, Pet pet);
}

Now it uses the value of the extension as the Parameter name, and the client compiles correctly.

I saw some other issues that may be related with this topic, #2892 #5903 #7256
And I believe there is also other option where the OneOf classes should be generated right? In this case the class OneOfDogCatLizard. But I couldn't generate these classes, do I need to pass diferente parameters to the generator cli?

So to sum up, if this change is technically correct I can complete the PR by fixing the unit tests and updating the documentation

Hugo

@bbdouglas (2017/07) @sreeshas (2017/08) @jfiala (2017/08) @lukoyanov (2017/09) @cbornet (2017/09) @jeff9finger (2018/01) @karismann (2019/03) @Zomzog (2019/04) @lwlee2608 (2019/10) @nmuesch (2021/01)

PR checklist

  • Read the contribution guidelines.
  • Pull Request title clearly describes the work in the pull request and Pull Request description provides details about how to validate the work. Missing information here may result in delayed response from the community.
  • If contributing template-only or documentation-only changes which will change sample output, build the project beforehand.
  • Run
    mvn clean package
    ./bin/generate-samples.sh
    ./bin/utils/export_docs_generators.sh
    
    to update all Petstore samples related to your fix.
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    For Windows users, please run the script in Git BASH.
  • File the PR against the correct branch: master, 5.1.x, 6.0.x
  • Copy the technical committee to review the pull request if your PR is targeting a particular programming language.

@auto-labeler auto-labeler bot added Client: Java WIP Work in Progress labels Jan 12, 2021
@auto-labeler
Copy link

auto-labeler bot commented Jan 12, 2021

👍 Thanks for opening this issue!
🏷 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.

@kuhnroyal
Copy link
Contributor

This does not work as soon as the type is not imported already in the API class or there is a model suffix/prefix configured.
After some investigation into the same problem, I now think that there is currently zero support for generating inline composed result/response/parameter in InlineModelResolver

@hugo-ma-alves
Copy link
Contributor Author

Thanks for the feedback @kuhnroyal
I'm interested in investigating this problem a bit more.
Do you have any example, open api spec or a sample, that I can use to replicate the situation you describe? it would be helpful for starting.

@hugo-ma-alves
Copy link
Contributor Author

@wing328 Do you have any example to reproduce this problem?

@nermin-imamovic
Copy link

openapi.zip

Can you test with this file.

When we can expect to resolve this :)

@wing328
Copy link
Member

wing328 commented Jun 9, 2022

About the UNKNOWN_BASE_TYPE issue, it should be fixed in v6.0.0. Please pull the latest to give it another try.

@wing328 wing328 closed this Jun 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Client: Java WIP Work in Progress
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants