StackOverflowError with recursive data model introduced with version 2.2.28
My project builds correctly using io.swagger.core.v3:swagger-jaxrs2-jakarta:2.2.27 io.swagger.core.v3:swagger-annotations-jakarta:2.2.27 as can be seen here: https://github.com/Yaytay/query-engine/actions/runs/13693736285
Bumping to io.swagger.core.v3:swagger-jaxrs2-jakarta:2.2.28 io.swagger.core.v3:swagger-annotations-jakarta:2.2.28
causes a StackOverflowError: https://github.com/Yaytay/query-engine/actions/runs/13693747582/job/38291540555#step:8:93660
uk.co.spudsoft.query.main.OpenApiModelConverter.resolve@69
io.swagger.v3.core.converter.ModelConverterContextImpl.resolve@97
io.swagger.v3.core.jackson.ModelResolver.resolve@745
uk.co.spudsoft.query.main.OpenApiModelConverter.resolve@70
io.swagger.v3.core.converter.ModelConverterContextImpl.resolve@97
io.swagger.v3.core.jackson.ModelResolver.resolve@493
uk.co.spudsoft.query.main.OpenApiModelConverter.resolve@70
io.swagger.v3.core.converter.ModelConverterContextImpl.resolve@97
io.swagger.v3.core.jackson.ModelResolver.resolve@745
uk.co.spudsoft.query.main.OpenApiModelConverter.resolve@70
io.swagger.v3.core.converter.ModelConverterContextImpl.resolve@97
io.swagger.v3.core.jackson.ModelResolver.resolve@745
uk.co.spudsoft.query.main.OpenApiModelConverter.resolve@70
io.swagger.v3.core.converter.ModelConverterContextImpl.resolve@97
io.swagger.v3.core.jackson.ModelResolver.resolveSubtypes@1665
io.swagger.v3.core.jackson.ModelResolver.resolve@906
uk.co.spudsoft.query.main.OpenApiModelConverter.resolve@70
io.swagger.v3.core.converter.ModelConverterContextImpl.resolve@97
io.swagger.v3.core.jackson.ModelResolver.resolve@745
uk.co.spudsoft.query.main.OpenApiModelConverter.resolve@70
io.swagger.v3.core.converter.ModelConverterContextImpl.resolve@97
io.swagger.v3.core.jackson.ModelResolver.resolve@745
uk.co.spudsoft.query.main.OpenApiModelConverter.resolve@70
io.swagger.v3.core.converter.ModelConverterContextImpl.resolve@97
io.swagger.v3.core.jackson.ModelResolver.resolveSubtypes@1665
io.swagger.v3.core.jackson.ModelResolver.resolve@906
uk.co.spudsoft.query.main.OpenApiModelConverter.resolve@70
io.swagger.v3.core.converter.ModelConverterContextImpl.resolve@97
io.swagger.v3.core.converter.ModelConverters.resolveAsResolvedSchema@192
io.swagger.v3.core.converter.ModelConverters.readAllAsResolvedSchema@182
io.swagger.v3.core.util.AnnotationsUtils.resolveSchemaFromType@897
io.swagger.v3.core.util.AnnotationsUtils.getSchema@1743
io.swagger.v3.core.util.AnnotationsUtils.getArraySchema@552
io.swagger.v3.core.jackson.ModelResolver.resolve@753
uk.co.spudsoft.query.main.OpenApiModelConverter.resolve@70
io.swagger.v3.core.converter.ModelConverterContextImpl.resolve@97
io.swagger.v3.core.jackson.ModelResolver.resolve@745
uk.co.spudsoft.query.main.OpenApiModelConverter.resolve@70
io.swagger.v3.core.converter.ModelConverterContextImpl.resolve@97
io.swagger.v3.core.jackson.ModelResolver.resolveSubtypes@1665
io.swagger.v3.core.jackson.ModelResolver.resolve@906
uk.co.spudsoft.query.main.OpenApiModelConverter.resolve@70
io.swagger.v3.core.converter.ModelConverterContextImpl.resolve@97
io.swagger.v3.core.converter.ModelConverters.resolveAsResolvedSchema@192
io.swagger.v3.core.converter.ModelConverters.readAllAsResolvedSchema@182
You can see that I have a custom ModelConverter in there, but taking that out didn't fix the problem, and leaving it in lets me capture the stack of types being resolved:
Resolving type: 614 [simple type, class boolean]:innerJoin (null)
Resolving type: 614 [collection type; class java.util.List, contains [simple type, class java.lang.String]]:parentIdColumns (null)
Resolving type: 614 [simple type, class uk.co.spudsoft.query.defn.SourcePipeline]:fieldDefns (null)
Resolving type: 615 [simple type, class uk.co.spudsoft.query.defn.Source]:source (null)
Resolving type: 616 [simple type, class uk.co.spudsoft.query.defn.SourceType]:type (null)
Resolving type: 616 uk.co.spudsoft.query.defn.SourceSql:null (null)
Resolving type: 617 [simple type, class java.lang.Integer]:maxPoolSize (null)
Resolving type: 617 [simple type, class java.time.Duration]:idleTimeout (null)
Resolving type: 618 [simple type, class long]:seconds (null)
Resolving type: 618 [collection type; class java.util.List, contains [simple type, class java.time.temporal.TemporalUnit]]:units (null)
Resolving type: 619 [simple type, class java.time.temporal.TemporalUnit]:units (null)
Resolving type: 620 [simple type, class java.time.Duration]:duration (null)
Resolving type: 617 [simple type, class java.lang.Boolean]:replaceDoubleQuotes (null)
Resolving type: 616 uk.co.spudsoft.query.defn.SourceTest:null (null)
Resolving type: 615 [collection type; class java.util.List, contains [simple type, class uk.co.spudsoft.query.defn.Processor]]:processors (null)
Resolving type: 616 [simple type, class uk.co.spudsoft.query.defn.Processor]:processors (null)
Resolving type: 617 uk.co.spudsoft.query.defn.ProcessorExpression:null (null)
Resolving type: 618 [simple type, class uk.co.spudsoft.query.defn.DataType]:fieldType (null)
Resolving type: 617 uk.co.spudsoft.query.defn.ProcessorGroupConcat:null (null)
Resolving type: 617 uk.co.spudsoft.query.defn.ProcessorLookup:null (null)
Resolving type: 618 [collection type; class java.util.List, contains [simple type, class uk.co.spudsoft.query.defn.ProcessorLookupField]]:lookupFields (null)
Resolving type: 619 [simple type, class uk.co.spudsoft.query.defn.ProcessorLookupField]:lookupFields (null)
Resolving type: 617 uk.co.spudsoft.query.defn.ProcessorMap:null (null)
Resolving type: 618 [collection type; class java.util.List, contains [simple type, class uk.co.spudsoft.query.defn.ProcessorMapLabel]]:relabels (null)
Resolving type: 619 [simple type, class uk.co.spudsoft.query.defn.ProcessorMapLabel]:relabels (null)
Resolving type: 617 uk.co.spudsoft.query.defn.ProcessorOffset:null (null)
Resolving type: 617 uk.co.spudsoft.query.defn.ProcessorQuery:null (null)
Resolving type: 617 uk.co.spudsoft.query.defn.ProcessorScript:null (null)
Resolving type: 617 uk.co.spudsoft.query.defn.ProcessorSort:null (null)
Resolving type: 615 uk.co.spudsoft.query.defn.Processor:null (null)
Resolving type: 616 [simple type, class java.lang.String]:name (null)
Resolving type: 616 [simple type, class uk.co.spudsoft.query.defn.ProcessorType]:type (null)
Resolving type: 616 [simple type, class uk.co.spudsoft.query.defn.Condition]:condition (null)
Resolving type: 616 uk.co.spudsoft.query.defn.ProcessorLimit:null (null)
Resolving type: 617 [simple type, class int]:limit (null)
Resolving type: 616 uk.co.spudsoft.query.defn.ProcessorDynamicField:null (null)
Resolving type: 617 [simple type, class boolean]:innerJoin (null)
Resolving type: 617 [collection type; class java.util.List, contains [simple type, class java.lang.String]]:parentIdColumns (null)
Resolving type: 617 [simple type, class uk.co.spudsoft.query.defn.SourcePipeline]:fieldDefns (null)
Resolving type: 618 [simple type, class uk.co.spudsoft.query.defn.Source]:source (null)
Resolving type: 619 [simple type, class uk.co.spudsoft.query.defn.SourceType]:type (null)
Resolving type: 619 uk.co.spudsoft.query.defn.SourceSql:null (null)
Resolving type: 620 [simple type, class java.lang.Integer]:maxPoolSize (null)
Resolving type: 620 [simple type, class java.time.Duration]:idleTimeout (null)
Resolving type: 621 [simple type, class long]:seconds (null)
Resolving type: 621 [collection type; class java.util.List, contains [simple type, class java.time.temporal.TemporalUnit]]:units (null)
The leading number there is the depth of the hierarchy, that should be going back to 0.
The SourcePipeline class contains a List of Processor objects, a Processor object can be a ProcessorDynamicField object, which contains a fieldDefns field which is of type SourcePipeline, and round it goes.
Still occurs with v2.2.30.
A simplified reproducer: https://github.com/Yaytay/swagger_core_4852_reproducer
The problem is caused by this change: https://github.com/swagger-api/swagger-core/compare/v2.2.27...v2.2.28#diff-bed6aab5e29942b1a575bded333604f9dfaeb2ef9475f1433266ece4e49f4fcb to pass in "true" as the final argument to AnnotationsUtils#getArraySchema.
And the reason this is a problem is that when ModelConverter#resolveAsResolvedSchema is called it creates a new ModelConverterContextImpl, which means it forgets that it has already processed that type.
Fairly minimal reproducer in swagger-core fork: https://github.com/Yaytay/swagger-core/tree/%234852
Same for me with 2.2.34
2.2.36 is still affected
Just rebased my reproducer onto the latest master and it still fails: https://github.com/Yaytay/swagger-core/tree/%234852
Not sure what we can do to get traction on this.
Removing the "true" argument fixes the problem and swagger-core builds cleanly. This either implies that it's redundant or that whoever added didn't add a unit test to demonstrate the need for it.
Anyone reading this and not the discussion on the PR: There is a unit test demonstrating the previous fix, but it's not in the swagger-core module. The whole multi-module repo needs to be built to test it, which I neglected to do.
The issue has been fixed in #5004 and will be included in the next release. Thank you @Yaytay for providing the solution