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.15k stars 6.41k forks source link

[BUG] Ref to another spec file doesn't work #1669

Open viralanomaly opened 5 years ago

viralanomaly commented 5 years ago
Description

My openapi spec is split into multiple files. In some cases, one of the subfiles will refer to a component from another.

openapi-generator version

3.3.4, not sure on regression

OpenAPI declaration file content or url
allOf:
  - $ref: 'common.yaml#/components/schemas/MyRemoteSchema'
  - $ref: '#/components/schemas/MyLocalSchema'
Command line used for generation
./openapi-generator-cli.sh generate -i openapi/openapi.yaml  -g kotlin-spring -c config.json

OR

/openapi-generator-cli.sh generate -i openapi/openapi.yaml -g spring -c config.json

config.json:

{
  "groupId": "com.myco.api",
  "artifactId": "my-thing",
  "artifactVersion": "0.0.0.1",
  "sourceFolder": "src/main/java",
  "title": "My Super Cool Thing",
  "interfaceOnly": false,
  "java8": true,
  "async": true,
  "reactive": false,
  "library": "spring-boot"
}
Steps to reproduce

Run the command given above. The output on the command line will be:

[main] WARN  o.o.codegen.utils.ModelUtils - Failed to get the schema name: common.yaml#/components/schemas/MyObject
[main] WARN  o.o.codegen.DefaultCodegen - Error obtaining the datatype from ref:common.yaml#/components/schemas/MyObject. Default to 'object'
Related issues/PRs

Nothing exact

Suggest a fix

It appears like the code in codegen.utils.ModelUtils for getSimpleRef is assuming that the string will always start with either #/components or #/definitions. It is valid yaml to have it be common.yaml#/components. I think that section of code should perhaps check if the reference contains #/components or #/definitions instead.

viralanomaly commented 5 years ago

I think this may be more general than just the spring versions I've tried. I tried generating python-flask and hit the same problem.

wing328 commented 5 years ago

What about using ./ to reference files? e.g.

allOf:
  - $ref: './common.yaml#/components/schemas/MyRemoteSchema'
  - $ref: '#/components/schemas/MyLocalSchema'
viralanomaly commented 5 years ago

I wasn't using the ./, but I added in and get the same behavior. This is the stack trace I get

  Exception: null
    at org.openapitools.codegen.DefaultGenerator.processOperation(DefaultGenerator.java:1039)
    at org.openapitools.codegen.DefaultGenerator.processPaths(DefaultGenerator.java:933)
    at org.openapitools.codegen.DefaultGenerator.generateApis(DefaultGenerator.java:511)
    at org.openapitools.codegen.DefaultGenerator.generate(DefaultGenerator.java:891)
    at org.openapitools.codegen.cmd.Generate.run(Generate.java:355)
    at org.openapitools.codegen.OpenAPIGenerator.main(OpenAPIGenerator.java:62)
Caused by: java.lang.NullPointerException
    at org.openapitools.codegen.utils.ModelUtils.isMapSchema(ModelUtils.java:329)
    at org.openapitools.codegen.DefaultCodegen.fromRequestBody(DefaultCodegen.java:4519)
    at org.openapitools.codegen.DefaultCodegen.fromOperation(DefaultCodegen.java:2452)
    at org.openapitools.codegen.languages.AbstractJavaCodegen.fromOperation(AbstractJavaCodegen.java:1135)
    at org.openapitools.codegen.DefaultGenerator.processOperation(DefaultGenerator.java:1007)
    ... 5 more
viralanomaly commented 5 years ago

I believe the stack trace is related to this warning from above:

[main] WARN  o.o.codegen.utils.ModelUtils - Failed to get the schema name: common.yaml#/components/schemas/MyComponent
[main] WARN  o.o.codegen.utils.ModelUtils - common.yaml#/components/schemas/MyComponent is not defined

The exception seems to happen when schema is null on line 329 of ModelUtils, which I expect is because of that undefined warning. That warning is how I came to suspect getSimpleRef in ModelUtils.

jmini commented 5 years ago

It appears like the code in codegen.utils.ModelUtils for getSimpleRef is assuming that the string will always start with either #/components or #/definitions. It is valid yaml to have it be common.yaml#/components. I think that section of code should perhaps check if the reference contains #/components or #/definitions instead.

As far as I know, it should be the case, because swagger-parser should bring all the schema into one spec while doing the parsing.

Can you have a look at the Swagger-Parser output. You can use a small java program like this:

    public static void main(final String[] args) throws Exception {
        final String url = "<path-to>/<your-main-spec>.yaml";

        ParseOptions options = new ParseOptions();
        options.setResolve(true);
        options.setFlatten(true);

        final OpenAPI oapi = new OpenAPIParser().readLocation(url, null, options).getOpenAPI();
        final String string = Yaml.mapper().writerWithDefaultPrettyPrinter().writeValueAsString(oapi);
        System.out.println(string);
    }

Could you post (for example on https://gist.github.com/) the 2 files (your main file and the common.yaml) to reproduce your issue?

viralanomaly commented 5 years ago

I will try to strip down my API and see how simple I can make it to still get the issue.