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

[Java]NullPointerException during codegen #12190

Closed
harid opened this issue Jun 23, 2023 · 6 comments
Closed

[Java]NullPointerException during codegen #12190

harid opened this issue Jun 23, 2023 · 6 comments
Assignees

Comments

@harid
Copy link

harid commented Jun 23, 2023

Getting NPE while generating codegen in Java. Stack trace attached below. YAML to repro the issue below.

Exception in thread "Thread-1" java.lang.NullPointerException
	at io.swagger.codegen.v3.generators.SchemaHandler.lambda$addInterfaces$1(SchemaHandler.java:196)
	at java.util.stream.MatchOps$1MatchSink.accept(MatchOps.java:90)
	at java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1361)
	at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126)
	at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:499)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:486)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
	at java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:230)
	at java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:196)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.anyMatch(ReferencePipeline.java:449)
	at io.swagger.codegen.v3.generators.SchemaHandler.addInterfaces(SchemaHandler.java:196)
	at io.swagger.codegen.v3.generators.SchemaHandler.processComposedSchema(SchemaHandler.java:77)
	at io.swagger.codegen.v3.generators.SchemaHandler.processComposedSchemas(SchemaHandler.java:35)
	at io.swagger.codegen.v3.ISchemaHandler.readProcessedModels(ISchemaHandler.java:30)
	at io.swagger.codegen.v3.DefaultGenerator.generateModels(DefaultGenerator.java:391)
	at io.swagger.codegen.v3.DefaultGenerator.generate(DefaultGenerator.java:788)
	at io.swagger.codegen.v3.cli.cmd.Generate.run(Generate.java:388)
	at java.lang.Thread.run(Thread.java:750)

Swagger-codegen version 3.0.43

"/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java" -jar swagger-codegen-cli.jar generate -i ./restapi_orig.json -l java -o ./gen

Was able to generate a short YAML that repro'ed the issue:

openapi: 3.0.0
info:
  title: "reproCase"
  version: "0.1"
paths:
  /test:
    description: test
    post:
      responses:
        '200':
          description: OK
          content:
            applicaton/xml:
              schema:
                  oneOf:
                  - $ref: "#/components/responses/r-match"
                  - $ref: "#/components/schemas/nomatch"
components:
  responses:
    r-match:
      $ref: "#/components/schemas/match"
    r-nomatch:
      $ref: "#/components/schemas/nomatch"
  schemas:
    match:
      type: string
    nomatch:
      type: string

If I change the ref, "#/components/responses/r-match" to "#/components/schemas/match", it works(no NPE). It is probably wrong to refer to a component-ized response within an inline response but I wish it would error out without an NPE. I was originally trying to component-ize the responses but later decided to do the response inline. When I still had the mistaken reference to the component-ized response it threw this exception. But it took a lot of whittling down a long YAML to discover that.

@harid
Copy link
Author

harid commented Jul 1, 2023

Updated with a YAML to repro.

@jeremydyoung
Copy link

I think I have a solution to this problem, but the code change belongs in https://github.com/swagger-api/swagger-codegen-generators

I think this yaml helps demonstrate the problem more clearly, because it does not require similarly named responses and schemas:

openapi: 3.0.0
info:
  title: "reproCase"
  version: "0.1"
paths:
  /test:
    post:
      description: test
      responses:
        '200':
          $ref: '#/components/responses/StandardOK'
components:
  responses:
    StandardOK:
      description: OK
      content:
        applicaton/xml:
          schema:
            $ref: '#/components/schemas/StandardResponse'
  schemas:
    StandardResponse:
      oneOf:
      - $ref: '#/components/schemas/schema1'
      - $ref: '#/components/schemas/schemaDoesNotExist'
    schema1:
      type: string
    schema2:
      type: string

Having something named nomatch in the example is misleading.

Using 3.0.46 I was able to reproduce:

Exception in thread "Thread-0" java.lang.NullPointerException: Cannot read field "classname" because "model" is null
	at io.swagger.codegen.v3.generators.SchemaHandler.lambda$addInterfaces$1(SchemaHandler.java:196)
	at java.base/java.util.stream.MatchOps$1MatchSink.accept(MatchOps.java:90)
	at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1602)
	at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
	at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:230)
	at java.base/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:196)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.anyMatch(ReferencePipeline.java:632)
	at io.swagger.codegen.v3.generators.SchemaHandler.addInterfaces(SchemaHandler.java:196)
	at io.swagger.codegen.v3.generators.SchemaHandler.processComposedSchema(SchemaHandler.java:77)
	at io.swagger.codegen.v3.generators.SchemaHandler.processComposedSchemas(SchemaHandler.java:35)
	at io.swagger.codegen.v3.ISchemaHandler.readProcessedModels(ISchemaHandler.java:30)
	at io.swagger.codegen.v3.DefaultGenerator.generateModels(DefaultGenerator.java:391)
	at io.swagger.codegen.v3.DefaultGenerator.generate(DefaultGenerator.java:788)
	at io.swagger.codegen.v3.cli.cmd.Generate.run(Generate.java:388)
	at java.base/java.lang.Thread.run(Thread.java:833)

3.0.41 had a slightly different error:

Exception in thread "Thread-1" java.lang.NullPointerException
	at io.swagger.codegen.v3.generators.SchemaHandler.lambda$addInterfaces$1(SchemaHandler.java:196)
	at java.util.stream.MatchOps$1MatchSink.accept(MatchOps.java:90)
	at java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1361)
	at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126)
	at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:499)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:486)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
	at java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:230)
	at java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:196)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.anyMatch(ReferencePipeline.java:516)
	at io.swagger.codegen.v3.generators.SchemaHandler.addInterfaces(SchemaHandler.java:196)
	at io.swagger.codegen.v3.generators.SchemaHandler.processComposedSchema(SchemaHandler.java:77)
	at io.swagger.codegen.v3.generators.SchemaHandler.processComposedSchemas(SchemaHandler.java:35)
	at io.swagger.codegen.v3.ISchemaHandler.readProcessedModels(ISchemaHandler.java:30)
	at io.swagger.codegen.v3.DefaultGenerator.generateModels(DefaultGenerator.java:391)
	at io.swagger.codegen.v3.DefaultGenerator.generate(DefaultGenerator.java:788)
	at io.swagger.codegen.v3.cli.cmd.Generate.run(Generate.java:388)
	at java.lang.Thread.run(Thread.java:750)

With my changes we get a sane error message:

12:54:35.186 [Thread-0] ERROR i.s.c.v3.generators.SchemaHandler - Could not find model for reference '#/components/schemas/schemaDoesNotExist' when processing 'StandardResponse' with json - {
  "oneOf" : [ {
    "$ref" : "#/components/schemas/schema1"
  }, {
    "$ref" : "#/components/schemas/schemaDoesNotExist"
  } ]
}

PR incoming

@harid
Copy link
Author

harid commented Jul 28, 2023

Thanks for looking into this. "match" and "nomatch" are more common in the Voice Recognition domain I work on.

One thing I want to point out: in my example YAML, all schemas exist. It is just referencing the response from "components" in the actual response definition caused the issue. Not sure if your example uncovered a new issue or if it covers the one highlighted by my example as well.

@jeremydyoung
Copy link

jeremydyoung commented Jul 28, 2023

Unfortunately, you are mixing up responses and schemas in your situation. Just because a response exists with a particular name does not mean that a schema exists with a particular name.

When using my updated code, you see the actual error:

15:01:16.194 [Thread-0] ERROR i.s.c.v3.generators.SchemaHandler - Could not find model for reference '#/components/responses/r-match' when processing 'inline_response_200' with json - {
  "oneOf" : [ {
    "$ref" : "#/components/responses/r-match"
  }, {
    "$ref" : "#/components/schemas/nomatch"
  } ]
}

The problem is that there is no SCHEMA with the name #/components/responses/r-match because that's the name of a response.

@harid
Copy link
Author

harid commented Jul 28, 2023

Ok, good. Looks like the fix produces a better error for my case as well.

Yes, as I admitted in my original description, referencing a response from "components" in the inline response was a mistake but few things led to that:

It is probably wrong to refer to a component-ized response within an inline response but I wish it would error out without an NPE. I was originally trying to component-ize the responses but later decided to do the response inline. When I still had the mistaken reference to the component-ized response it threw this exception. But it took a lot of whittling down a long YAML to discover that.

The request was to get a better error response which your fix does provide, it appears.

@micryc
Copy link
Contributor

micryc commented Apr 30, 2024

@micryc micryc closed this as completed Apr 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants