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

Stack Overflow / infinite recursion in PolymorphicModelConverter.findComposedSchemas #2801

Open
martinitus opened this issue Dec 2, 2024 · 2 comments
Labels
incomplete incomplete description: Make sure you Provide a Minimal, Reproducible Example - with HelloController

Comments

@martinitus
Copy link

Describe the bug
I am trying to work around the problem described here with the workaround described here. TLDR: I want to have a description on a type that is not defined by the type, but by the context where the type is used.

To Reproduce

  • spring-boot 3.3
  • springdoc-openapi 2.70
// sorry for the Kotlin code, my Java is a little outdated...
import io.swagger.v3.oas.annotations.media.Schema
import kotlinx.serialization.Serializable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController


@Serializable
@Schema(description = "Generic description")
data class KeyValue(
    val key: String,
    val value: String,
)

@Serializable
@Schema
data class SomeDTO(
    @Schema(description = "Description A", allOf = [KeyValue::class]) val field_a: KeyValue,
    @Schema(description = "Description B", allOf = [KeyValue::class]) val field_b: KeyValue,
)

@RestController
@RequestMapping("/test")
class TestAdapter() {
    
    @PostMapping("/test")
    fun create(@RequestBody some: SomeDTO) {
        TODO()
    }
}

Expected behavior
Expected Open API Json

... component/schemas/
"SomeDTO": {
        "required": [
          "field_a",
          "field_b"
        ],
        "type": "object",
        "properties": {
          "field_a": {
            "type": "object",
            "description": "Description A",
            "allOf": [
              {
                "$ref": "#/components/schemas/KeyValue"
              }
            ]
          },
          "field_b": {
            "type": "object",
            "description": "Description B",
            "allOf": [
              {
                "$ref": "#/components/schemas/KeyValue"
              }
            ]
          }
        }
      },

Screenshots

It loads (no StackOverflow) and renders correctly, when I change type of field_a and field_b to String. But that's obviously not what I want.

@Schema(description = "Description A", allOf = [KeyValue::class]) val field_a: String,
@Schema(description = "Description B", allOf = [KeyValue::class]) val field_b: String,

image

** Stack Trace**

11:10:45.221 [http-nio-8080-exec-1] /v3/api-docs INFO  d.b...RequestLoggingFilter - method=GET
11:10:45.806 [http-nio-8080-exec-1]  ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed: java.lang.StackOverflowError] with root cause
java.lang.StackOverflowError: null
	at org.springdoc.core.converters.PolymorphicModelConverter.lambda$findComposedSchemas$2(PolymorphicModelConverter.java:147)
	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 org.springdoc.core.converters.PolymorphicModelConverter.lambda$findComposedSchemas$3(PolymorphicModelConverter.java:147)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
	at java.base/java.util.TreeMap$ValueSpliterator.forEachRemaining(TreeMap.java:3215)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575)
	at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
	at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616)
	at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622)
	at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627)
	at org.springdoc.core.converters.PolymorphicModelConverter.findComposedSchemas(PolymorphicModelConverter.java:149)
@bnasslahsen
Copy link
Contributor

@martinitus,

Not reproducible.
Feel free to provide a Minimal, Reproducible Example - with HelloController that reproduces the problem.

This ticket will be closed, but can be reopened if your provide the reproducible sample.

@bnasslahsen bnasslahsen added the incomplete incomplete description: Make sure you Provide a Minimal, Reproducible Example - with HelloController label Dec 7, 2024
@martinitus
Copy link
Author

martinitus commented Dec 7, 2024

@bnasslahsen

Here you go: https://github.com/martinitus/springdoc-openapi-sample

Run app and open localhost:8080/swagger-ui.html. 💥

I've seen you have kotlin tests in here, and I tried to get them going on my non-work windows pc for like 15minutes, but then gave up. Should be easy to add one test scenario that includes this :-)

@bnasslahsen bnasslahsen reopened this Dec 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
incomplete incomplete description: Make sure you Provide a Minimal, Reproducible Example - with HelloController
Projects
None yet
Development

No branches or pull requests

2 participants