Skip to content

Commit 0775180

Browse files
committed
Restentpoints with same name get mix up. Fixes #2876
1 parent cce8e8b commit 0775180

File tree

9 files changed

+292
-15
lines changed

9 files changed

+292
-15
lines changed

Diff for: springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocConfiguration.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@
126126
import org.springframework.web.bind.annotation.RestControllerAdvice;
127127
import org.springframework.web.context.request.async.DeferredResult;
128128

129+
import static org.springdoc.core.utils.Constants.GLOBAL_OPEN_API_CUSTOMIZER;
129130
import static org.springdoc.core.utils.Constants.SPRINGDOC_DEPRECATING_CONVERTER_ENABLED;
130131
import static org.springdoc.core.utils.Constants.SPRINGDOC_ENABLED;
131132
import static org.springdoc.core.utils.Constants.SPRINGDOC_POLYMORPHIC_CONVERTER_ENABLED;
@@ -654,7 +655,7 @@ ParameterObjectNamingStrategyCustomizer parameterObjectNamingStrategyCustomizer(
654655
* @return the global open api customizer
655656
*/
656657
@Bean
657-
@ConditionalOnMissingBean
658+
@ConditionalOnMissingBean(name = GLOBAL_OPEN_API_CUSTOMIZER)
658659
@Lazy(false)
659660
GlobalOpenApiCustomizer globalOpenApiCustomizer() {
660661
return new OperationIdCustomizer();

Diff for: springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocHateoasConfiguration.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ CollectionModelContentConverter collectionModelContentConverter(HateoasHalProvid
101101
* @return the open api customizer
102102
* @see org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider) org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)org.springframework.hateoas.mediatype.hal.Jackson2HalModule.HalLinkListSerializer#serialize(Links, JsonGenerator, SerializerProvider)
103103
*/
104-
@Bean(Constants.LINKS_SCHEMA_CUSTOMISER)
105-
@ConditionalOnMissingBean(name = Constants.LINKS_SCHEMA_CUSTOMISER)
104+
@Bean(Constants.LINKS_SCHEMA_CUSTOMIZER)
105+
@ConditionalOnMissingBean(name = Constants.LINKS_SCHEMA_CUSTOMIZER)
106106
@Lazy(false)
107107
GlobalOpenApiCustomizer linksSchemaCustomizer(HateoasHalProvider halProvider, SpringDocConfigProperties springDocConfigProperties) {
108108
if (!halProvider.isHalEnabled()) {

Diff for: springdoc-openapi-starter-common/src/main/java/org/springdoc/core/customizers/SpringDocCustomizers.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
import org.springframework.context.ApplicationContextAware;
4040
import org.springframework.util.CollectionUtils;
4141

42-
import static org.springdoc.core.utils.Constants.LINKS_SCHEMA_CUSTOMISER;
42+
import static org.springdoc.core.utils.Constants.LINKS_SCHEMA_CUSTOMIZER;
4343

4444
/**
4545
* The type Spring doc customizers.
@@ -223,7 +223,7 @@ public Optional<Set<GlobalOpenApiMethodFilter>> getGlobalOpenApiMethodFilters()
223223
public void afterPropertiesSet() {
224224
//add the default customizers
225225
Map<String, OpenApiCustomizer> existingOpenApiCustomizers = context.getBeansOfType(OpenApiCustomizer.class);
226-
if (!CollectionUtils.isEmpty(existingOpenApiCustomizers) && existingOpenApiCustomizers.containsKey(LINKS_SCHEMA_CUSTOMISER))
227-
this.openApiCustomizers.ifPresent(openApiCustomizersList -> openApiCustomizersList.add(existingOpenApiCustomizers.get(LINKS_SCHEMA_CUSTOMISER)));
226+
if (!CollectionUtils.isEmpty(existingOpenApiCustomizers) && existingOpenApiCustomizers.containsKey(LINKS_SCHEMA_CUSTOMIZER))
227+
this.openApiCustomizers.ifPresent(openApiCustomizersList -> openApiCustomizersList.add(existingOpenApiCustomizers.get(LINKS_SCHEMA_CUSTOMIZER)));
228228
}
229229
}

Diff for: springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/Constants.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,12 @@ public final class Constants {
407407
/**
408408
* The constant LINKS_SCHEMA_CUSTOMISER.
409409
*/
410-
public static final String LINKS_SCHEMA_CUSTOMISER = "linksSchemaCustomizer";
410+
public static final String LINKS_SCHEMA_CUSTOMIZER = "linksSchemaCustomizer";
411+
412+
/**
413+
* The constant GLOBAL_OPEN_API_CUSTOMIZER.
414+
*/
415+
public static final String GLOBAL_OPEN_API_CUSTOMIZER = "globalOpenApiCustomizer";
411416

412417
/**
413418
* The constant SPRINGDOC_SORT_CONVERTER_ENABLED.

Diff for: springdoc-openapi-starter-common/src/test/java/org/springdoc/core/configuration/SpringDocHateoasConfigurationTest.java

+8-8
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import static org.assertj.core.api.Assertions.assertThat;
1414
import static org.mockito.Mockito.mock;
15-
import static org.springdoc.core.utils.Constants.LINKS_SCHEMA_CUSTOMISER;
15+
import static org.springdoc.core.utils.Constants.LINKS_SCHEMA_CUSTOMIZER;
1616

1717
class SpringDocHateoasConfigurationTest {
1818

@@ -33,8 +33,8 @@ void linksSchemaCustomizerShouldBeRegistered() {
3333
.run(context -> {
3434
assertThat(context).getBeanNames(GlobalOpenApiCustomizer.class)
3535
.hasSize(2)
36-
.contains(LINKS_SCHEMA_CUSTOMISER);
37-
assertThat(context.getBean(LINKS_SCHEMA_CUSTOMISER)).isExactlyInstanceOf(OpenApiHateoasLinksCustomizer.class);
36+
.contains(LINKS_SCHEMA_CUSTOMIZER);
37+
assertThat(context.getBean(LINKS_SCHEMA_CUSTOMIZER)).isExactlyInstanceOf(OpenApiHateoasLinksCustomizer.class);
3838
});
3939
}
4040

@@ -56,7 +56,7 @@ void linksSchemaCustomizerShouldBeRegisteredWithMultipleGlobalOpenApiCustomizer(
5656
.run(context -> {
5757
assertThat(context).getBeanNames(GlobalOpenApiCustomizer.class)
5858
.hasSize(2)
59-
.containsExactlyInAnyOrder(LINKS_SCHEMA_CUSTOMISER, "globalOpenApiCustomizer");
59+
.containsExactlyInAnyOrder(LINKS_SCHEMA_CUSTOMIZER, "globalOpenApiCustomizer");
6060
});
6161
}
6262

@@ -74,12 +74,12 @@ void linksSchemaCustomizerShouldNotBeRegisteredIfBeanWithSameNameAlreadyExists()
7474
SpringDocConfigProperties.class,
7575
SpringDocHateoasConfiguration.class
7676
))
77-
.withBean(LINKS_SCHEMA_CUSTOMISER, GlobalOpenApiCustomizer.class, () -> mock(GlobalOpenApiCustomizer.class))
77+
.withBean(LINKS_SCHEMA_CUSTOMIZER, GlobalOpenApiCustomizer.class, () -> mock(GlobalOpenApiCustomizer.class))
7878
.run(context -> {
7979
assertThat(context).getBeanNames(GlobalOpenApiCustomizer.class)
80-
.hasSize(1)
81-
.containsExactly(LINKS_SCHEMA_CUSTOMISER);
82-
assertThat(context.getBean(LINKS_SCHEMA_CUSTOMISER)).isNotExactlyInstanceOf(OpenApiHateoasLinksCustomizer.class);
80+
.hasSize(2)
81+
.contains(LINKS_SCHEMA_CUSTOMIZER);
82+
assertThat(context.getBean(LINKS_SCHEMA_CUSTOMIZER)).isNotExactlyInstanceOf(OpenApiHateoasLinksCustomizer.class);
8383
});
8484
}
8585
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package test.org.springdoc.api.v31.app240;
2+
3+
import java.util.HashSet;
4+
import java.util.Optional;
5+
import java.util.Set;
6+
7+
import io.swagger.v3.oas.annotations.Parameter;
8+
9+
import org.springframework.http.MediaType;
10+
import org.springframework.http.ResponseEntity;
11+
import org.springframework.web.bind.annotation.GetMapping;
12+
import org.springframework.web.bind.annotation.PatchMapping;
13+
import org.springframework.web.bind.annotation.PathVariable;
14+
import org.springframework.web.bind.annotation.PostMapping;
15+
import org.springframework.web.bind.annotation.RequestBody;
16+
import org.springframework.web.bind.annotation.RequestMapping;
17+
import org.springframework.web.bind.annotation.RequestParam;
18+
import org.springframework.web.bind.annotation.RestController;
19+
20+
@RestController
21+
@RequestMapping("/demo")
22+
public class DemoRestController {
23+
24+
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
25+
public Set<String> getDemo(
26+
@Parameter(required = false, description = "Very important description.")
27+
@RequestParam(name = "darstellung", required = false) final Optional<String> darstellung) {
28+
return new HashSet<>();
29+
}
30+
31+
@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
32+
public ResponseEntity<?> setDemo(@RequestBody final String str) {
33+
return ResponseEntity.noContent().build();
34+
}
35+
36+
@GetMapping(value = "/{vvpId}", produces = MediaType.APPLICATION_JSON_VALUE)
37+
public String getDemo(@PathVariable("vvpId") final Long vvpId) {
38+
return "Test";
39+
}
40+
41+
@PatchMapping("/{vvpId}")
42+
public ResponseEntity<?> patchDemo(@PathVariable("vvpId") final Long idVerfahren,
43+
@RequestBody() final String jsonPatch,
44+
final Optional<Boolean> statusKinderAendern) {
45+
return ResponseEntity.noContent().build();
46+
}
47+
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package test.org.springdoc.api.v31.app240;
2+
3+
import org.springdoc.core.customizers.OpenApiCustomizer;
4+
import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
5+
6+
import org.springframework.context.annotation.Bean;
7+
import org.springframework.context.annotation.Configuration;
8+
import org.springframework.http.HttpRequest;
9+
10+
@Configuration
11+
public class OpenApiConfig {
12+
13+
@Bean
14+
public OpenApiCustomizer openApiCustomiser() {
15+
return openApi -> {
16+
17+
};
18+
}
19+
20+
@Bean
21+
ServerBaseUrlCustomizer serverBaseUrlCustomizer() {
22+
return new ServerBaseUrlCustomizer() {
23+
24+
@Override
25+
public String customize(final String serverBaseUrl,
26+
final HttpRequest request) {
27+
// TODO Auto-generated method stub
28+
return null;
29+
}
30+
31+
};
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * *
6+
* * * * *
7+
* * * * * * Copyright 2019-2025 the original author or authors.
8+
* * * * * *
9+
* * * * * * Licensed under the Apache License, Version 2.0 (the "License");
10+
* * * * * * you may not use this file except in compliance with the License.
11+
* * * * * * You may obtain a copy of the License at
12+
* * * * * *
13+
* * * * * * https://www.apache.org/licenses/LICENSE-2.0
14+
* * * * * *
15+
* * * * * * Unless required by applicable law or agreed to in writing, software
16+
* * * * * * distributed under the License is distributed on an "AS IS" BASIS,
17+
* * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* * * * * * See the License for the specific language governing permissions and
19+
* * * * * * limitations under the License.
20+
* * * * *
21+
* * * *
22+
* * *
23+
* *
24+
*
25+
*/
26+
27+
package test.org.springdoc.api.v31.app240;
28+
29+
import test.org.springdoc.api.v31.AbstractSpringDocTest;
30+
31+
import org.springframework.boot.autoconfigure.SpringBootApplication;
32+
import org.springframework.test.context.TestPropertySource;
33+
34+
@TestPropertySource(properties = "springdoc.api-docs.resolve-schema-properties=true" )
35+
public class SpringDocApp240Test extends AbstractSpringDocTest {
36+
37+
@SpringBootApplication
38+
static class SpringDocTestApp {}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
{
2+
"openapi": "3.1.0",
3+
"info": {
4+
"title": "OpenAPI definition",
5+
"version": "v0"
6+
},
7+
"paths": {
8+
"/demo": {
9+
"get": {
10+
"tags": [
11+
"demo-rest-controller"
12+
],
13+
"operationId": "getDemo",
14+
"parameters": [
15+
{
16+
"name": "darstellung",
17+
"in": "query",
18+
"description": "Very important description.",
19+
"required": false,
20+
"schema": {
21+
"type": "string"
22+
}
23+
}
24+
],
25+
"responses": {
26+
"200": {
27+
"description": "OK",
28+
"content": {
29+
"application/json": {
30+
"schema": {
31+
"type": "array",
32+
"items": {
33+
"type": "string"
34+
},
35+
"uniqueItems": true
36+
}
37+
}
38+
}
39+
}
40+
}
41+
},
42+
"post": {
43+
"tags": [
44+
"demo-rest-controller"
45+
],
46+
"operationId": "setDemo",
47+
"requestBody": {
48+
"content": {
49+
"application/json": {
50+
"schema": {
51+
"type": "string"
52+
}
53+
}
54+
},
55+
"required": true
56+
},
57+
"responses": {
58+
"200": {
59+
"description": "OK",
60+
"content": {
61+
"*/*": {
62+
"schema": {
63+
"type": "object"
64+
}
65+
}
66+
}
67+
}
68+
}
69+
}
70+
},
71+
"/demo/{vvpId}": {
72+
"get": {
73+
"tags": [
74+
"demo-rest-controller"
75+
],
76+
"operationId": "getDemo_1",
77+
"parameters": [
78+
{
79+
"name": "vvpId",
80+
"in": "path",
81+
"required": true,
82+
"schema": {
83+
"type": "integer",
84+
"format": "int64"
85+
}
86+
}
87+
],
88+
"responses": {
89+
"200": {
90+
"description": "OK",
91+
"content": {
92+
"application/json": {
93+
"schema": {
94+
"type": "string"
95+
}
96+
}
97+
}
98+
}
99+
}
100+
},
101+
"patch": {
102+
"tags": [
103+
"demo-rest-controller"
104+
],
105+
"operationId": "patchDemo",
106+
"parameters": [
107+
{
108+
"name": "vvpId",
109+
"in": "path",
110+
"required": true,
111+
"schema": {
112+
"type": "integer",
113+
"format": "int64"
114+
}
115+
},
116+
{
117+
"name": "statusKinderAendern",
118+
"in": "query",
119+
"required": false,
120+
"schema": {
121+
"type": "boolean"
122+
}
123+
}
124+
],
125+
"requestBody": {
126+
"content": {
127+
"application/json": {
128+
"schema": {
129+
"type": "string"
130+
}
131+
}
132+
},
133+
"required": true
134+
},
135+
"responses": {
136+
"200": {
137+
"description": "OK",
138+
"content": {
139+
"*/*": {
140+
"schema": {
141+
"type": "object"
142+
}
143+
}
144+
}
145+
}
146+
}
147+
}
148+
}
149+
},
150+
"components": {}
151+
}

0 commit comments

Comments
 (0)