Skip to content

IllegalStateException when having multiple endpoints differentiated by header value #1253

Closed
@Neloop

Description

@Neloop

Describe the bug
We are currently exploring ways how to version our REST API in Spring application. During the research we also tried how the different versioning ways work with springdoc and we found out that custom header versioning does not cope well with springdoc. When generating OpenAPI for the controller below we are experiencing IllegalStateException, because of that OpenAPI JSON cannot be generated.

To Reproduce
Steps to reproduce the behavior:

  • spring-boot 2.5.3
  • springdoc-openapi-ui 1.5.10
  • Controller with following 2 endpoints:
@RestController
public class VersionController {

  @GetMapping(value = "groups", headers = "X-Version=1")
  public GroupV1 groupV1() {
      return null;
  }

  @GetMapping(value = "groups", headers = "X-Version=2")
  public GroupV2 groupV2() {
      return null;
  }
}
  • Produced exception on Swagger generation:
java.lang.IllegalStateException: Duplicate key class Parameter {
    name: X-Version
    in: header
    description: null
    required: null
    deprecated: null
    allowEmptyValue: null
    style: null
    explode: null
    allowReserved: null
    schema: class StringSchema {
        class Schema {
            type: string
            format: null
            $ref: null
            description: null
            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
            not: null
            properties: null
            additionalProperties: null
            nullable: null
            readOnly: null
            writeOnly: null
            example: null
            externalDocs: null
            deprecated: null
            discriminator: null
            xml: null
        }
    }
    examples: null
    example: null
    content: null
    $ref: null
}
               at org.springdoc.core.AbstractRequestService.lambda$getParameterLinkedHashMap$5(AbstractRequestService.java:297) ~[springdoc-openapi-common-1.5.10.jar:1.5.10]
               at java.base/java.util.HashMap.merge(HashMap.java:1297) ~[na:na]
               at java.base/java.util.stream.Collectors.lambda$toMap$68(Collectors.java:1658) ~[na:na]
               at java.base/java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169) ~[na:na]
               at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655) ~[na:na]
               at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
               at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
               at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[na:na]
               at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
               at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) ~[na:na]
               at org.springdoc.core.AbstractRequestService.getParameterLinkedHashMap(AbstractRequestService.java:293) ~[springdoc-openapi-common-1.5.10.jar:1.5.10]
               at org.springdoc.core.AbstractRequestService.build(AbstractRequestService.java:277) ~[springdoc-openapi-common-1.5.10.jar:1.5.10]
               at org.springdoc.api.AbstractOpenApiResource.calculatePath(AbstractOpenApiResource.java:391) ~[springdoc-openapi-common-1.5.10.jar:1.5.10]
               at org.springdoc.api.AbstractOpenApiResource.calculatePath(AbstractOpenApiResource.java:528) ~[springdoc-openapi-common-1.5.10.jar:1.5.10]
               at org.springdoc.webmvc.api.OpenApiResource.calculatePath(OpenApiResource.java:261) ~[springdoc-openapi-webmvc-core-1.5.10.jar:1.5.10]
               at org.springdoc.webmvc.api.OpenApiResource.getPaths(OpenApiResource.java:213) ~[springdoc-openapi-webmvc-core-1.5.10.jar:1.5.10]
               at org.springdoc.api.AbstractOpenApiResource.getOpenApi(AbstractOpenApiResource.java:287) ~[springdoc-openapi-common-1.5.10.jar:1.5.10]
               at org.springdoc.webmvc.api.OpenApiResource.openapiJson(OpenApiResource.java:176) ~[springdoc-openapi-webmvc-core-1.5.10.jar:1.5.10]
               at org.springdoc.webmvc.api.OpenApiWebMvcResource.openapiJson(OpenApiWebMvcResource.java:116) ~[springdoc-openapi-webmvc-core-1.5.10.jar:1.5.10]
...

Expected behavior

  • Springdoc is expected to generate OpenAPI JSON without throwing exception

Metadata

Metadata

Assignees

No one assigned

    Labels

    invalidThis doesn't seem right

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions