Skip to content

Commit 588a1a2

Browse files
committed
IllegalStateException: Duplicate key when two endpoints at the same URL with same header exist. Fixes #1985.
1 parent 597b98c commit 588a1a2

File tree

6 files changed

+154
-3
lines changed

6 files changed

+154
-3
lines changed

springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/GenericParameterService.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -362,10 +362,13 @@ Schema calculateSchema(Components components, ParameterInfo parameterInfo, Reque
362362

363363
if (parameterInfo.getParameterModel() == null || parameterInfo.getParameterModel().getSchema() == null) {
364364
Type type = ReturnTypeParser.getType(methodParameter);
365-
if (type instanceof Class clazz && optionalWebConversionServiceProvider.isPresent()) {
365+
if (type instanceof Class && !((Class<?>) type).isEnum() && optionalWebConversionServiceProvider.isPresent()) {
366366
WebConversionServiceProvider webConversionServiceProvider = optionalWebConversionServiceProvider.get();
367-
if (!MethodParameterPojoExtractor.isSwaggerPrimitiveType((Class) type) && methodParameter.getParameterType().getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class) == null)
368-
type = webConversionServiceProvider.getSpringConvertedType(methodParameter.getParameterType());
367+
if (!MethodParameterPojoExtractor.isSwaggerPrimitiveType((Class) type) && methodParameter.getParameterType().getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class) == null){
368+
Class<?> springConvertedType = webConversionServiceProvider.getSpringConvertedType(methodParameter.getParameterType());
369+
if (!(String.class.equals(springConvertedType) && ((Class<?>) type).isEnum()))
370+
type = springConvertedType;
371+
}
369372
}
370373
schemaN = SpringDocAnnotationsUtils.extractSchema(components, type, jsonView, methodParameter.getParameterAnnotations());
371374
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package test.org.springdoc.api.v30.app200;
2+
3+
import com.fasterxml.jackson.annotation.JsonCreator;
4+
import com.fasterxml.jackson.annotation.JsonValue;
5+
6+
public enum FooBar {
7+
FOO("foo"),
8+
BAR("bar");
9+
10+
private String value;
11+
12+
FooBar(String value) {
13+
this.value = value;
14+
}
15+
16+
@JsonValue
17+
public String getValue() {
18+
return value;
19+
}
20+
21+
@Override
22+
public String toString() {
23+
return String.valueOf(value);
24+
}
25+
26+
@JsonCreator
27+
public static FooBar fromValue(String value) {
28+
for (FooBar b : FooBar.values()) {
29+
if (b.value.equals(value)) {
30+
return b;
31+
}
32+
}
33+
throw new IllegalArgumentException("Unexpected value '" + value + "'");
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package test.org.springdoc.api.v30.app200;
2+
3+
4+
import org.springframework.web.bind.annotation.GetMapping;
5+
import org.springframework.web.bind.annotation.PathVariable;
6+
import org.springframework.web.bind.annotation.RestController;
7+
8+
@RestController
9+
public class FooBarController {
10+
@GetMapping(value = "/example/{fooBar}")
11+
public String getFooBar(@PathVariable FooBar fooBar) {
12+
return fooBar.name();
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package test.org.springdoc.api.v30.app200;
2+
3+
4+
import org.springframework.core.convert.converter.Converter;
5+
import org.springframework.stereotype.Component;
6+
7+
@Component
8+
public class FooBarConverter implements Converter<String, FooBar> {
9+
10+
@Override
11+
public FooBar convert(String source) {
12+
return FooBar.fromValue(source);
13+
}
14+
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * * Copyright 2019-2022 the original author or authors.
6+
* * * *
7+
* * * * Licensed under the Apache License, Version 2.0 (the "License");
8+
* * * * you may not use this file except in compliance with the License.
9+
* * * * You may obtain a copy of the License at
10+
* * * *
11+
* * * * https://www.apache.org/licenses/LICENSE-2.0
12+
* * * *
13+
* * * * Unless required by applicable law or agreed to in writing, software
14+
* * * * distributed under the License is distributed on an "AS IS" BASIS,
15+
* * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* * * * See the License for the specific language governing permissions and
17+
* * * * limitations under the License.
18+
* * *
19+
* *
20+
*
21+
*/
22+
23+
package test.org.springdoc.api.v30.app200;
24+
25+
import test.org.springdoc.api.v30.AbstractSpringDocV30Test;
26+
27+
import org.springframework.boot.autoconfigure.SpringBootApplication;
28+
29+
public class SpringDocApp200Test extends AbstractSpringDocV30Test {
30+
31+
@SpringBootApplication
32+
static class SpringDocTestApp {}
33+
34+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"openapi": "3.0.1",
3+
"info": {
4+
"title": "OpenAPI definition",
5+
"version": "v0"
6+
},
7+
"servers": [
8+
{
9+
"url": "http://localhost",
10+
"description": "Generated server url"
11+
}
12+
],
13+
"paths": {
14+
"/example/{fooBar}": {
15+
"get": {
16+
"tags": [
17+
"foo-bar-controller"
18+
],
19+
"operationId": "getFooBar",
20+
"parameters": [
21+
{
22+
"name": "fooBar",
23+
"in": "path",
24+
"required": true,
25+
"schema": {
26+
"type": "string",
27+
"enum": [
28+
"foo",
29+
"bar"
30+
]
31+
}
32+
}
33+
],
34+
"responses": {
35+
"200": {
36+
"description": "OK",
37+
"content": {
38+
"*/*": {
39+
"schema": {
40+
"type": "string"
41+
}
42+
}
43+
}
44+
}
45+
}
46+
}
47+
}
48+
},
49+
"components": {}
50+
}

0 commit comments

Comments
 (0)