Skip to content

[BUG] [codegen] external $ref in parameters not getting resolved #1976

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

Open
jphorx opened this issue Jan 24, 2019 · 29 comments
Open

[BUG] [codegen] external $ref in parameters not getting resolved #1976

jphorx opened this issue Jan 24, 2019 · 29 comments

Comments

@jphorx
Copy link

jphorx commented Jan 24, 2019

Description

When attempting to generate code from an OpenAPI document that included $ref , all of the references failed to be resolved and are included in files in the same directory. I've seen other's report this issue before, but it is supposed to be resolved in the version I tested with.

openapi-generator version

3.3.4

OpenAPI declaration file content or url

https://github.com/jdegre/5GC_APIs.git

Command line used for generation

% java -jar openapi-generator-cli.jar generate -i ./TS29514_Npcf_PolicyAuthorization.yaml -g java-vertx -o ./PCF/PolicyAuth

Steps to reproduce

Working in Ubuntu 16.04 ( if that matters ).

I followed the instructions here ( https://openapi-generator.tech/docs/installation ) and installed the JAR, to pull down the 3.3.4 version of the library. I cloned OpenAPI yaml specifications from this repo: https://github.com/jdegre/5GC_APIs.git

Tried to generate with this command:

% java -jar openapi-generator-cli.jar generate -i ./TS29514_Npcf_PolicyAuthorization.yaml -g java-vertx -o ./PCF/PolicyAuth

The output was as follows:

[main] WARN io.swagger.v3.parser.OpenAPIV3Parser - Exception while reading:
java.lang.NullPointerException: null
at io.swagger.v3.parser.ResolverCache.updateLocalRefs(ResolverCache.java:162)
at io.swagger.v3.parser.ResolverCache.loadRef(ResolverCache.java:152)
at io.swagger.v3.parser.processors.ExternalRefProcessor.processRefToExternalResponse(ExternalRefProcessor.java:205)
at io.swagger.v3.parser.processors.ResponseProcessor.processReferenceResponse(ResponseProcessor.java:76)
at io.swagger.v3.parser.processors.ResponseProcessor.processResponse(ResponseProcessor.java:38)
at io.swagger.v3.parser.processors.OperationProcessor.processOperation(OperationProcessor.java:56)
at io.swagger.v3.parser.processors.PathsProcessor.processPaths(PathsProcessor.java:83)
at io.swagger.v3.parser.OpenAPIResolver.resolve(OpenAPIResolver.java:49)
at io.swagger.v3.parser.OpenAPIV3Parser.readLocation(OpenAPIV3Parser.java:53)
at io.swagger.parser.OpenAPIParser.readLocation(OpenAPIParser.java:19)
at org.openapitools.codegen.config.CodegenConfigurator.toClientOptInput(CodegenConfigurator.java:552)
at org.openapitools.codegen.cmd.Generate.run(Generate.java:354)
at org.openapitools.codegen.OpenAPIGenerator.main(OpenAPIGenerator.java:62)
[main] WARN o.o.codegen.utils.ModelUtils - Failed to get the schema name: ./TS29571_CommonData.yaml#/components/schemas/RouteToLocation
[main] WARN o.o.codegen.utils.ModelUtils - Failed to get the schema name: ./TS29571_CommonData.yaml#/components/schemas/RouteToLocation
[main] WARN o.o.codegen.utils.ModelUtils - Failed to get the schema name: ./TS29571_CommonData.yaml#/components/schemas/PresenceInfo
[main] WARN o.o.codegen.utils.ModelUtils - Failed to get the schema name: ./TS29571_CommonData.yaml#/components/schemas/PresenceInfo
.
. LOTS more warnings like these, omitted to keep this concise
.
[main] WARN o.o.codegen.utils.ModelUtils - Failed to get the schema name: ./TS29571_CommonData.yaml#/components/responses/503
[main] WARN o.o.codegen.utils.ModelUtils - Failed to get the schema name: ./TS29571_CommonData.yaml#/components/responses/default
Exception in thread "main" org.openapitools.codegen.SpecValidationException: There were issues with the specification. The option can be disabled via validateSpec (Maven/Gradle) or --skip-validate-spec (CLI).
| Error count: 1, Warning count: 0
Errors:
-null

at org.openapitools.codegen.config.CodegenConfigurator.toClientOptInput(CodegenConfigurator.java:569)
at org.openapitools.codegen.cmd.Generate.run(Generate.java:354)
at org.openapitools.codegen.OpenAPIGenerator.main(OpenAPIGenerator.java:62)
Related issues/PRs

This one seems very similar:
#455

Suggest a fix
@auto-labeler
Copy link

auto-labeler bot commented Jan 24, 2019

👍 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.

@loganknecht
Copy link

+1 on this. I really wish I could use references 😭

@jmini
Copy link
Member

jmini commented Jan 30, 2019

From the stacktrace, it seems that the problem is located in Swagger-Parser library.

Please have a look at how Swagger-Parser is parsing your file and try to produce a minimal example. Sample Java Snippet:

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

OpenAPI openAPI = openApiParser.readLocation(inputSpec, null, options).getOpenAPI();
String string = Yaml.mapper().writerWithDefaultPrettyPrinter().writeValueAsString(openAPI);

System.out.println(string);

Maven coordinates of the dependency for your test project:

<dependency>
    <groupId>io.swagger.core.v3</groupId>
    <artifactId>swagger-core</artifactId>
    <version>2.0.6</version>
</dependency>

Let me know if you need help.

@jphorx
Copy link
Author

jphorx commented Feb 1, 2019

I've modified the petstore.yaml example to reproduce the issue. Original found here: https://github.com/OAI/OpenAPI-Specification/tree/master/examples/v3.0/petstore.yaml.

petstore.zip

@jphorx jphorx closed this as completed Feb 1, 2019
@jphorx jphorx reopened this Feb 1, 2019
@jphorx
Copy link
Author

jphorx commented Feb 26, 2019

As suggested, I wrote some code to directly parse the OpenAPI spec files from this location ( https://github.com/jdegre/5GC_APIs.git ), with the target being a locally corrected version of TS29514_Npcf_PolicyAuthorization.yaml.

When using the swagger-parser directly, I was able to consume this yaml, including the external references successfully.

The crude test program I wrote to try processing the same yaml files is attached as well, just run the jar and add an argument that is the qualified yaml file name.
swagger-parser-bug.zip

I've attached just the files yaml files I used below
5GC_APIs.zip

@jphorx
Copy link
Author

jphorx commented Feb 26, 2019

I've modified the petstore.yaml example to reproduce the issue. Original found here: https://github.com/OAI/OpenAPI-Specification/tree/master/examples/v3.0/petstore.yaml.

petstore.zip

I found a mistake in these yaml files, they should be ignored.

@jphorx
Copy link
Author

jphorx commented Mar 19, 2019

I have re-tested this with the v4.0.0-beta2 release and was able to process all of the models, so this was addressed somehow?

@jweisman
Copy link

jweisman commented Apr 3, 2019

My test is not working with the latest v4.0.0-beta2 release.

java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -i https://raw.githubusercontent.com/swagger-api/swagger-codegen/50d5cf092cb05e76d88f8900664c0a248fdd0d95/modules/swagger-codegen/src/test/resources/3_0_0/petstore.json -g ruby -o ~/tmp/ruby

Results in:

...
[main] WARN  o.o.codegen.utils.ModelUtils - Failed to get the schema name: #/ExtUser
[main] WARN  o.o.codegen.utils.ModelUtils - #/ExtUser is not defined
...

In swagger-codegen I had to use setResolveFully to get it to work and added a PR for that setting.

@afobo
Copy link

afobo commented Apr 3, 2019

I had the same issue with openapi-generator-maven-plugin version 3.3.4 and 5G API spec (namely, TS29510_Nnrf_NFManagement.yaml).
Root cause is the issue in swagger-parser fixed in swagger-api/swagger-parser@a989c2a

So, upgrade of swagger-parser to 2.0.5 solved the problem:

        <plugin>
            <groupId>org.openapitools</groupId>
            <artifactId>openapi-generator-maven-plugin</artifactId>
            <version>3.3.4</version>
            <dependencies>
                <dependency>
                    <groupId>io.swagger.parser.v3</groupId>
                    <artifactId>swagger-parser</artifactId>
                    <version>2.0.5</version>
                </dependency>
            </dependencies>
        </plugin>

@jmini
Copy link
Member

jmini commented Apr 10, 2019

Can you retry with 4.0.0-beta3? we have updated the swagger-parser version with #2262.

@Mistgun
Copy link

Mistgun commented Apr 11, 2019

@jmini I have encountered similar issue, on v.4.0.0-beta3 it happens:

[main] WARN  io.swagger.v3.parser.OpenAPIV3Parser - Exception while reading:
java.lang.RuntimeException: Unable to load RELATIVE ref: ../../../components.yml path:
  at io.swagger.v3.parser.util.RefUtils.readExternalRef(RefUtils.java:204)
  at io.swagger.v3.parser.ResolverCache.loadRef(ResolverCache.java:119)
  at io.swagger.v3.parser.processors.ParameterProcessor.processParameters(ParameterProcessor.java:85)
  at io.swagger.v3.parser.processors.OperationProcessor.processOperation(OperationProcessor.java:39)
  at io.swagger.v3.parser.processors.PathsProcessor.processPaths(PathsProcessor.java:84)
  at io.swagger.v3.parser.OpenAPIResolver.resolve(OpenAPIResolver.java:49)
  at io.swagger.v3.parser.OpenAPIV3Parser.readLocation(OpenAPIV3Parser.java:53)
  at io.swagger.parser.OpenAPIParser.readLocation(OpenAPIParser.java:19)
  at org.openapitools.codegen.config.CodegenConfigurator.toClientOptInput(CodegenConfigurator.java:606)
  at org.openapitools.codegen.cmd.Generate.run(Generate.java:367)
  at org.openapitools.codegen.OpenAPIGenerator.main(OpenAPIGenerator.java:60)
Caused by: java.lang.RuntimeException: Could not find ../../../components.yml on the classpath
  at io.swagger.v3.parser.util.ClasspathHelper.loadFileFromClasspath(ClasspathHelper.java:31)
  at io.swagger.v3.parser.util.RefUtils.readExternalRef(RefUtils.java:198)
  ... 10 common frames omitted
Exception in thread "main" org.openapitools.codegen.SpecValidationException: There were issues with the specification. The option can be disabled via validateSpec (Maven/Gradle) or --skip-validate-spec (CLI).
 | Error count: 1, Warning count: 0
Errors:
  -Unable to load RELATIVE ref: ../../../components.yml path: /Users/x/x/doc

  at org.openapitools.codegen.config.CodegenConfigurator.toClientOptInput(CodegenConfigurator.java:626)
  at org.openapitools.codegen.cmd.Generate.run(Generate.java:367)
  at org.openapitools.codegen.OpenAPIGenerator.main(OpenAPIGenerator.java:60) 

Even though, validation command passes successfully..
I tried the same with version 3.2.0 and it worked.

@jweisman
Copy link

jweisman commented Apr 15, 2019

Hi @jmini - it's still not working in v4.0.0-beta3 release.

java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -i https://raw.githubusercontent.com/swagger-api/swagger-codegen/50d5cf092cb05e76d88f8900664c0a248fdd0d95/modules/swagger-codegen/src/test/resources/3_0_0/petstore.json -g ruby -o ~/tmp/ruby

Results in:

...
[main] WARN  o.o.codegen.utils.ModelUtils - Failed to get the schema name: #/ExtUser
[main] WARN  o.o.codegen.utils.ModelUtils - Failed to get the schema name: #/ExtUser
...

The test definition is available so you can run the same command to test it. Thanks!

@jmini
Copy link
Member

jmini commented Apr 30, 2019

@jweisman Thank you for the feedback... Sorry for the delay.
I am trying to understand what is wrong here. Were is the spec that you are using as Input?

@cvgaviao
Copy link

@jmini, this issue was resolved only in the last week in the swagger-parser repository. I think you have not published that yet...

@jmini
Copy link
Member

jmini commented May 1, 2019

I have prepared PR #2775 to update Swagger-Parser

@jweisman
Copy link

jweisman commented May 1, 2019

@jmini - the spec I'm using is
https://raw.githubusercontent.com/swagger-api/swagger-codegen/50d5cf092cb05e76d88f8900664c0a248fdd0d95/modules/swagger-codegen/src/test/resources/3_0_0/petstore.json

The offending line is:

"application/json": {
              "schema": {
                "$ref": "./ext_user.json#/ext_user"
              }

The referenced file exists in the same path.

@jmini
Copy link
Member

jmini commented May 7, 2019

I have updated Swagger-Parser.
Can you check the latest 4.0.0-SNAPSHOT version of OpenAPI Generator?

@lacksfish
Copy link

For the impatient:

To fix my problem, I've used https://github.com/APIDevTools/json-schema-ref-parser (after turning my main yaml spec into json) and de-referenced all the $ref's automatically with the aforementioned tool.

Then, I was able to generate the client code :)

PSA: This is a hotfix and any code generated should be well tested.

@jweisman
Copy link

Hi @jmini - I downloaded the (now release) version of 4.0.0 and I'm getting the same behavior.

java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -i https://raw.githubusercontent.com/swagger-api/swagger-codegen/50d5cf092cb05e76d88f8900664c0a248fdd0d95/modules/swagger-codegen/src/test/resources/3_0_0/petstore.json -g ruby -o ~/tmp/ruby

Results in:

...
[main] WARN  o.o.codegen.utils.ModelUtils - Failed to get the schema name: #/ExtUser
[main] WARN  o.o.codegen.utils.ModelUtils - Failed to get the schema name: #/ExtUser
...

The test definition is available so you can run the same command to test it. Thanks!

Note also that:

In swagger-codegen I had to use setResolveFully to get it to work and added a PR for that setting.

@ghilainm
Copy link

I have the same problem with multiple level of JSON references using only local files with version 4.0.0.
Settings in ParseOptions resolve = true and resolveFully = true seems to solve the issue.

I had to override the class on the classpath to be able to change this option. It should maybe be exposed in the plugin options in the future.

@jmini
Copy link
Member

jmini commented Jul 10, 2019

With 4.0.3 we have updated Swagger-Parser, and I think that they now better handle reference. Can you please retry?

@jmini
Copy link
Member

jmini commented Jul 10, 2019

In swagger-codegen I had to use setResolveFully to get it to work

The problem with setResolveFully is that it is de-referencing the $ref:

With this input:

openapi: 3.0.1
info:
  title: ping test
  version: '1.0'
servers:
  - url: 'http://localhost:9999/'
paths:
  /ping:
    get:
      operationId: pingGet
      responses:
        '201':
          description: OK
          content:
            '*/*':
               schema:
                 $ref: "#/components/schemas/MainObj"
components:
  schemas:
    SomeObj:
      type: object
      properties:
        id:
          type: integer
          format: int64
    MainObj:
      type: object
      properties:
        lorem:
          $ref: "#/components/schemas/SomeObj"
        ipsum:
          type: string

The output of Swagger-Parser is

openapi: 3.0.1
info:
  title: ping test
  version: "1.0"
servers:
- url: http://localhost:9999/
paths:
  /ping:
    get:
      operationId: pingGet
      responses:
        201:
          description: OK
          content:
            '*/*':
              schema:
                type: object
                properties:
                  lorem:
                    type: object
                    properties:
                      id:
                        type: integer
                        format: int64
                  ipsum:
                    type: string
components:
  schemas:
    SomeObj:
      type: object
      properties:
        id:
          type: integer
          format: int64
    MainObj:
      type: object
      properties:
        lorem:
          type: object
          properties:
            id:
              type: integer
              format: int64
        ipsum:
          type: string

In the operation, there is no information anymore about the models defined in components/schema that are used in pingGet operation.
The components section could be completely ignored (the schemas there are unused).

I did not try it, but my guess is that OpenAPI-Generator will generator other models than the one defined in components/schema.

I do not believe that this is what the users want.

@jweisman
Copy link

Hi @jmini - same with 4.0.3.

java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -i https://raw.githubusercontent.com/swagger-api/swagger-codegen/50d5cf092cb05e76d88f8900664c0a248fdd0d95/modules/swagger-codegen/src/test/resources/3_0_0/petstore.json -g ruby -o ~/tmp/ruby

Results in:

...
[main] WARN  o.o.codegen.utils.ModelUtils - Failed to get the schema name: #/ExtUser
[main] WARN  o.o.codegen.utils.ModelUtils - Failed to get the schema name: #/ExtUser
...

The test definition is available so you can run the same command to test it. Thanks!

Out of curiosity- does this sample spec work for you? Perhaps it's something I'm doing wrong?

@nmandya
Copy link

nmandya commented Dec 25, 2019

Is there any update on this? I just tried with both version 4.2.2 and 4.2.3 and the schemas defined under components/schemas and referenced using $ref are not included in the generated HTML documentation. Thanks.

@stephengroat
Copy link

Also having this issue, tried to make a replica case in swagger-parser with swagger-api/swagger-parser#1338

@RaduFurnea
Copy link

I'm having the same problem when migrating an existent spec from version 2 to 3, and I would really like to avoid having to move all models defined in the common file to each spec file.

@lacksfish
Copy link

If you scroll up a bit, I offered a hacky quick fix, which worked for me.

@stephengroat
Copy link

stephengroat commented Apr 16, 2020

thanks for the reminder @lacksfish

here's a small node script that implements the idea, run with node app.js INPUT_FILE_JSON OUTPUT_FILE_JSON:

const $RefParser = require("@apidevtools/json-schema-ref-parser");
const fs = require('fs');

let args = process.argv.slice(2);
let rawdata = fs.readFileSync(args[0]);
let input = JSON.parse(rawdata);
$RefParser.dereference(input, (err, schema) => {
  if (err) {
    console.error(err);
  }
  else {
    let data = JSON.stringify(schema, null, 2);
    fs.writeFileSync(args[1], data);
  }
})

@mutech
Copy link

mutech commented Sep 10, 2020

What is the status of this issue?

EDIT: From what I can see, the problem is that when resolving repeated refs, the parser uses the original base URL (the root) instead or resolving relative to the referencing document.

Sorry, I'm ranting a bit here.

I would think such a file resolution issue would be important enough to fix it before 20 months.

I'm currently generating a JSON-schema for each tool that uses schema and falls apart for different reasons, I have sliced, slashed, splitted, merged and partially merged schema, I am patching output with regexes and I am now doing the same for each openapi tool I am using, because no single tool is able to understand any schema dialect and handle it correctly.

I so miss the time when I could work with XSD.

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