Using the following OpenAPI file below, the following error occurs:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOfRange(Arrays.java:3664)
at java.lang.String.<init>(String.java:207)
at java.lang.StringBuilder.toString(StringBuilder.java:407)
at com.fasterxml.jackson.core.util.TextBuffer.contentsAsString(TextBuffer.java:404)
at com.fasterxml.jackson.core.io.SegmentedStringWriter.getAndClear(SegmentedStringWriter.java:83)
at com.fasterxml.jackson.databind.ObjectWriter.writeValueAsString(ObjectWriter.java:999)
at io.swagger.v3.core.util.Json.pretty(Json.java:24)
at org.openapitools.codegen.DefaultCodegen.fromModel(DefaultCodegen.java:1627)
at org.openapitools.codegen.languages.JavascriptClientCodegen.fromModel(JavascriptClientCodegen.java:842)
at org.openapitools.codegen.DefaultCodegen.fromOperation(DefaultCodegen.java:2437)
at org.openapitools.codegen.DefaultGenerator.processOperation(DefaultGenerator.java:1021)
at org.openapitools.codegen.DefaultGenerator.processPaths(DefaultGenerator.java:944)
at org.openapitools.codegen.DefaultGenerator.generateApis(DefaultGenerator.java:516)
at org.openapitools.codegen.DefaultGenerator.generate(DefaultGenerator.java:902)
at org.openapitools.codegen.cmd.Generate.run(Generate.java:368)
at org.openapitools.codegen.OpenAPIGenerator.main(OpenAPIGenerator.java:60)
This happens both in openapi-generator-cli-4.0.0-20190325.151629-451.jar and openapi-generator-cli-3.3.4.jar.
swagger: '2.0'
info:
version: "1.0"
title: DEV-2369
# ===============================================================================
# Paths
# ===============================================================================
paths:
/users/responders:
get:
operationId: getUserResponderList
summary: Gets a list of Responder objects
responses:
'200':
description: A list of Responder objects
schema:
$ref: '#/definitions/ResponderList'
'500':
$ref: '#/responses/InternalServerError'
default:
$ref: '#/responses/TotallyUnexpectedResponse'
/responders:
post:
operationId: createResponder
parameters:
- name: responder
in: body
required: true
schema:
$ref: '#/definitions/ResponderCreate'
responses:
'201':
description: A Responder object
schema:
$ref: '#/definitions/Responder'
'400':
$ref: '#/responses/BadRequest'
'500':
$ref: '#/responses/InternalServerError'
default:
$ref: '#/responses/TotallyUnexpectedResponse'
# ===============================================================================
# Definitions
# ===============================================================================
definitions:
ID:
type: integer
format: int64
readOnly: true
Reviewer:
type: object
properties:
name:
type: string
maxLength: 100
SuccessfulBugFix:
type: object
properties:
reviewers:
type: array
minItems: 0
maxItems: 100
uniqueItems: true
items:
$ref: '#/definitions/Reviewer'
ResponderProfileCreate:
type: object
properties:
successfulBugFixes:
type: array
minItems: 0
maxItems: 100
uniqueItems: true
items:
$ref: '#/definitions/SuccessfulBugFix'
ResponderProfile:
type: object
properties:
successfulBugFixes:
type: array
minItems: 0
maxItems: 100
uniqueItems: true
items:
$ref: '#/definitions/SuccessfulBugFix'
Error:
type: object
required:
- message
properties:
message:
type: string
User:
type: object
properties:
id:
$ref: '#/definitions/ID'
Responder:
type: object
properties:
id:
$ref: '#/definitions/ID'
responderProfile:
$ref: '#/definitions/ResponderProfile'
# Used only for the creation of a new Responder
ResponderCreate:
type: object
properties:
responderProfile:
$ref: '#/definitions/ResponderProfileCreate'
ResponderList:
type: object
required:
- items
properties:
items:
type: array
minItems: 0
maxItems: 1000
uniqueItems: true
items:
$ref: '#/definitions/Responder'
# ===============================================================================
# Responses
# ===============================================================================
responses:
InternalServerError:
description: An unexpected error occured.
schema:
$ref: '#/definitions/Error'
BadRequest:
description: Bad request; could not perform requested operation.
EntityDoesNotExist:
description: Entity does not exist.
TotallyUnexpectedResponse:
description: A totally unexpected response
java -jar ./openapi-generator-cli-3.3.4.jar generate -i ../openapi.yaml -l javascript --additional-properties usePromises=true --additional-properties useES6=false -o ./javascript/
also:
java -jar ./openapi-generator-cli-4.0.0-20190325.151629-451.jar generate -i ../openapi.yaml -g javascript -o ./javascript/
also:
java -jar ./openapi-generator-cli-4.0.0-20190325.151629-451.jar generate -i ../openapi.yaml -g javascript --additional-properties usePromises=true --additional-properties useES6=false -o ./javascript/
openapi.yaml.None that I am aware of.
Not sure.
馃憤 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.
by changing
definitions:
Reviewer:
type: string
the issue does not occur.
somehow the memory issue occurs due to the deep-nesting of objects
Super strange, ain't it? :)
It is. Maybe you could investigate the problem using the stacktrace?
We side-stepped the problem for now.
Unfortunately, I am not a Java developer and don't have time to go deep into this, as I am terribly busy with my own startup... but we will offer a bounty for fixing this, as soon as BountySource wake up and pay our previous bounties to those claiming them.
it seems that DefaultCodegen::fromModel is called twice for name = "ResponderList"
the first call works and schema in https://github.com/OpenAPITools/openapi-generator/blob/46e8ccbd1ec7482f665e63eaf036f16e1af432e3/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java#L1627 contains the following object:
schema
class ObjectSchema {
class Schema {
title: null
multipleOf: null
maximum: null
exclusiveMaximum: null
minimum: null
exclusiveMinimum: null
maxLength: null
minLength: null
pattern: null
maxItems: null
minItems: null
uniqueItems: null
maxProperties: null
minProperties: null
required: [items]
type: null
not: null
properties: {items=class ArraySchema {
class Schema {
title: null
multipleOf: null
maximum: null
exclusiveMaximum: null
minimum: null
exclusiveMinimum: null
maxLength: null
minLength: null
pattern: null
maxItems: 1000
minItems: 0
uniqueItems: true
maxProperties: null
minProperties: null
required: null
type: null
not: null
properties: null
additionalProperties: null
description: null
format: null
$ref: null
nullable: null
readOnly: null
writeOnly: null
example: null
externalDocs: null
deprecated: null
discriminator: null
xml: null
}
type: array
items: class Schema {
title: null
multipleOf: null
maximum: null
exclusiveMaximum: null
minimum: null
exclusiveMinimum: null
maxLength: null
minLength: null
pattern: null
maxItems: null
minItems: null
uniqueItems: null
maxProperties: null
minProperties: null
required: null
type: null
not: null
properties: null
additionalProperties: null
description: null
format: null
$ref: #/components/schemas/Responder
nullable: null
readOnly: null
writeOnly: null
example: null
externalDocs: null
deprecated: null
discriminator: null
xml: null
}
}}
additionalProperties: null
description: null
format: null
$ref: null
nullable: null
readOnly: null
writeOnly: null
example: null
externalDocs: null
deprecated: null
discriminator: null
xml: null
}
type: object
defaultObject: null
}
but in the second call, schema contains the following object:
schema
class ObjectSchema {
class Schema {
title: null
multipleOf: null
maximum: null
exclusiveMaximum: null
minimum: null
exclusiveMinimum: null
maxLength: null
minLength: null
pattern: null
maxItems: null
minItems: null
uniqueItems: null
maxProperties: null
minProperties: null
required: [items]
type: null
not: null
properties: {items=class ArraySchema {
class Schema {
title: null
multipleOf: null
maximum: null
exclusiveMaximum: null
minimum: null
exclusiveMinimum: null
maxLength: null
minLength: null
pattern: null
maxItems: 1000
minItems: 0
uniqueItems: true
maxProperties: null
minProperties: null
required: null
type: null
not: null
properties: null
additionalProperties: null
description: null
format: null
$ref: null
nullable: null
readOnly: null
writeOnly: null
example: null
externalDocs: null
deprecated: null
discriminator: null
xml: null
}
type: array
items: class Schema {
title: null
multipleOf: null
maximum: null
exclusiveMaximum: null
minimum: null
exclusiveMinimum: null
maxLength: null
minLength: null
pattern: null
maxItems: null
minItems: null
uniqueItems: null
maxProperties: null
minProperties: null
required: null
type: null
not: null
properties: null
additionalProperties: null
description: null
format: null
$ref: #/components/schemas/Responder
nullable: null
readOnly: null
writeOnly: null
example: null
externalDocs: null
deprecated: null
discriminator: null
xml: null
}
}}
additionalProperties: null
description: null
format: null
$ref: null
nullable: null
readOnly: null
writeOnly: null
example: {items=[Ljava.lang.Object;@1cfd1875}
externalDocs: null
deprecated: null
discriminator: null
xml: null
}
type: object
defaultObject: null
}
The only difference seems to be
example: {items=[Ljava.lang.Object;@1cfd1875}
where items is an object with 1000 entries similar to
{responderProfile={successfulBugFixes=[Ljava.lang.Object;@1af7f54a}, id=0}

it seems that the example-generation with 1000 entries is clearly an overkill and leads to a memory issue for many nested objects.
the relevant code that generates the examples is located here:
https://github.com/OpenAPITools/openapi-generator/blob/46e8ccbd1ec7482f665e63eaf036f16e1af432e3/modules/openapi-generator/src/main/java/org/openapitools/codegen/examples/ExampleGenerator.java#L234
it creates arrays of length maxItems.
@advance512 a simple workaround for you:
explicitly define an example in the models where you use type: array properties in combination with maxItems, e.g.:
definitions:
ResponderList:
type: object
required:
- items
properties:
items:
type: array
minItems: 0
maxItems: 1000
uniqueItems: true
items:
$ref: '#/definitions/Responder'
example:
items: []
so this is your adapted spec where the issue does not occur anymore:
adapted spec
swagger: '2.0'
info:
version: "1.0"
title: DEV-2369
# ===============================================================================
# Paths
# ===============================================================================
paths:
/users/responders:
get:
operationId: getUserResponderList
summary: Gets a list of Responder objects
responses:
'200':
description: A list of Responder objects
schema:
$ref: '#/definitions/ResponderList'
'500':
$ref: '#/responses/InternalServerError'
default:
$ref: '#/responses/TotallyUnexpectedResponse'
/responders:
post:
operationId: createResponder
parameters:
- name: responder
in: body
required: true
schema:
$ref: '#/definitions/ResponderCreate'
responses:
'201':
description: A Responder object
schema:
$ref: '#/definitions/Responder'
'400':
$ref: '#/responses/BadRequest'
'500':
$ref: '#/responses/InternalServerError'
default:
$ref: '#/responses/TotallyUnexpectedResponse'
# ===============================================================================
# Definitions
# ===============================================================================
definitions:
ID:
type: integer
format: int64
readOnly: true
Reviewer:
type: object
properties:
name:
type: string
maxLength: 100
SuccessfulBugFix:
type: object
properties:
reviewers:
type: array
minItems: 0
maxItems: 100
uniqueItems: true
items:
$ref: '#/definitions/Reviewer'
example:
reviewers: []
ResponderProfileCreate:
type: object
properties:
successfulBugFixes:
type: array
minItems: 0
maxItems: 100
uniqueItems: true
items:
$ref: '#/definitions/SuccessfulBugFix'
ResponderProfile:
type: object
properties:
successfulBugFixes:
type: array
minItems: 0
maxItems: 100
uniqueItems: true
items:
$ref: '#/definitions/SuccessfulBugFix'
example:
successfulBugFixes: []
Error:
type: object
required:
- message
properties:
message:
type: string
User:
type: object
properties:
id:
$ref: '#/definitions/ID'
Responder:
type: object
properties:
id:
$ref: '#/definitions/ID'
responderProfile:
$ref: '#/definitions/ResponderProfile'
# Used only for the creation of a new Responder
ResponderCreate:
type: object
properties:
responderProfile:
$ref: '#/definitions/ResponderProfileCreate'
ResponderList:
type: object
required:
- items
properties:
items:
type: array
minItems: 0
maxItems: 1000
uniqueItems: true
items:
$ref: '#/definitions/Responder'
example:
items: []
# ===============================================================================
# Responses
# ===============================================================================
responses:
InternalServerError:
description: An unexpected error occured.
schema:
$ref: '#/definitions/Error'
BadRequest:
description: Bad request; could not perform requested operation.
EntityDoesNotExist:
description: Entity does not exist.
TotallyUnexpectedResponse:
description: A totally unexpected response
your maxItems: 1000 is just a little below the value 1024 that would trigger a warning
https://github.com/OpenAPITools/openapi-generator/blob/46e8ccbd1ec7482f665e63eaf036f16e1af432e3/modules/openapi-generator/src/main/java/org/openapitools/codegen/examples/ExampleGenerator.java#L234-L244
Anyway, even the trigger value of 1024 is not useful if the spec contains many nested objects.
If you feel like this answer solves the problem for you, feel free to contribute a bounty here: https://github.com/bithost-gmbh/ngx-mat-select-search#support-development
I think this issue should be closed as it is not really a bug that can be prevented in every possible situation.
Thanks for your help, @macjohnny.
Say, why does the generator instantiate a thousand objects of responderProfile? What is the point?
If we're talking about an example object that is being generated - first of all, where is it used? Second, why create the maximum items in an array, and not just.. 3 items, for example? Or 5? Is it not much more confusing, having an example with 1000 objects?
I think this also makes the generator itself slower than it should be.
Letting the generator crash is definitely a bug that should be fixed. It doesn't communicate anything of value to the person using the generator - there is no clear route of "how to fix the problem". A proper fix would be to cap the amount of items created in the example, I think.
We will definitely contribute a bounty. Could you cap the items in the example to 3 or 5?
I think you are right, limiting the number of objects to 5 does make sense.
The generated example is used here
https://github.com/OpenAPITools/openapi-generator/blob/3a0d520c389ddff9300f15f4e47967c8ff8b12c0/modules/openapi-generator/src/main/resources/JavaSpring/methodBody.mustache#L10-L13
and results in some server api implementations in an example response, e.g.
https://github.com/OpenAPITools/openapi-generator/blob/3a0d520c389ddff9300f15f4e47967c8ff8b12c0/samples/server/petstore/springboot/src/main/java/org/openapitools/api/PetApi.java#L85-L89
I opened PR https://github.com/OpenAPITools/openapi-generator/pull/2536 to limit the number of example items in an array to max. 5, which fixes the issue (tested with your original spec).
Thanks for your help, @macjohnny.
@advance512 you are welcome. Thanks for your bounty!
Most helpful comment
@advance512 you are welcome. Thanks for your bounty!