Skip to content

Commit c09135a

Browse files
committed
Fix: Property resolution not working for extensions in @OpenAPIDefinition
1 parent ca5fdf5 commit c09135a

File tree

4 files changed

+76
-8
lines changed

4 files changed

+76
-8
lines changed

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -636,9 +636,11 @@ public Class<? extends Annotation> annotationType() {
636636
*/
637637
private void buildOpenAPIWithOpenAPIDefinition(OpenAPI openAPI, OpenAPIDefinition apiDef, Locale locale) {
638638
boolean isOpenapi3 = propertyResolverUtils.isOpenapi31();
639-
Map<String, Object> extensions = AnnotationsUtils.getExtensions(isOpenapi3, apiDef.info().extensions());
640639
// info
641-
AnnotationsUtils.getInfo(apiDef.info(), true).map(info -> resolveProperties(info, extensions, locale)).ifPresent(openAPI::setInfo);
640+
AnnotationsUtils.getInfo(apiDef.info(), true).map(info -> {
641+
Map<String, Object> extensions = AnnotationsUtils.getExtensions(isOpenapi3, apiDef.info().extensions());
642+
return resolveProperties(info, extensions, locale);
643+
}).ifPresent(openAPI::setInfo);
642644
// OpenApiDefinition security requirements
643645
securityParser.getSecurityRequirements(apiDef.security()).ifPresent(openAPI::setSecurity);
644646
// OpenApiDefinition external docs
@@ -702,7 +704,7 @@ private Info resolveProperties(Info info, Map<String, Object> extensions, Locale
702704
resolveProperty(contact::getUrl, contact::url, propertyResolverUtils, locale);
703705
}
704706

705-
if (propertyResolverUtils.isResolveExtensionsProperties() && extensions != null) {
707+
if (extensions != null) {
706708
Map<String, Object> extensionsResolved = propertyResolverUtils.resolveExtensions(locale, extensions);
707709
if (propertyResolverUtils.isOpenapi31())
708710
extensionsResolved.forEach(info::addExtension31);
@@ -713,7 +715,6 @@ private Info resolveProperties(Info info, Map<String, Object> extensions, Locale
713715
return info;
714716
}
715717

716-
717718
/**
718719
* Resolve property.
719720
*

springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/PropertyResolverUtils.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,21 +224,27 @@ public Map<String, Object> resolveExtensions(Locale locale, Map<String, Object>
224224
Map<String, Object> extensionsResolved = new HashMap<>();
225225
extensions.forEach((key, value) -> {
226226
String keyResolved = resolve(key, locale);
227-
if (value instanceof HashMap<?, ?>) {
227+
if (value instanceof HashMap<?, ?> valueAsMap) {
228228
Map<String, Object> valueResolved = new HashMap<>();
229-
((HashMap<?, ?>) value).forEach((key1, value1) -> {
229+
valueAsMap.forEach((key1, value1) -> {
230230
String key1Resolved = resolve(key1.toString(), locale);
231231
String value1Resolved = resolve(value1.toString(), locale);
232232
valueResolved.put(key1Resolved, value1Resolved);
233233
});
234234
extensionsResolved.put(keyResolved, valueResolved);
235235
}
236-
else
236+
else if (value instanceof String valueAsString) {
237+
String valueResolved = resolve(valueAsString, locale);
238+
extensionsResolved.put(keyResolved, valueResolved);
239+
}
240+
else {
237241
extensionsResolved.put(keyResolved, value);
242+
}
238243
});
239244
return extensionsResolved;
240245
}
241-
else
246+
else {
242247
return extensions;
248+
}
243249
}
244250
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package test.org.springdoc.api.v31.app245;
2+
3+
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
4+
import io.swagger.v3.oas.annotations.extensions.Extension;
5+
import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
6+
import io.swagger.v3.oas.annotations.info.Info;
7+
import org.springframework.boot.autoconfigure.SpringBootApplication;
8+
import org.springframework.web.bind.annotation.GetMapping;
9+
import org.springframework.web.bind.annotation.RestController;
10+
11+
@SpringBootApplication
12+
@OpenAPIDefinition(
13+
info = @Info(
14+
title = "My App",
15+
version = "${springdoc.version}",
16+
extensions = {
17+
@Extension(properties = {
18+
@ExtensionProperty(name = "x-build-time", value = "${git.build.time}")
19+
})
20+
}
21+
)
22+
)
23+
@RestController
24+
public class HelloController {
25+
26+
@GetMapping("/hello")
27+
public String hello() {
28+
return "hello";
29+
}
30+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package test.org.springdoc.api.v31.app245;
2+
3+
import static org.hamcrest.Matchers.is;
4+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
5+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
6+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
7+
8+
import org.junit.jupiter.api.Test;
9+
import org.springframework.beans.factory.annotation.Autowired;
10+
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
11+
import org.springframework.boot.test.context.SpringBootTest;
12+
import org.springframework.test.web.servlet.MockMvc;
13+
14+
@SpringBootTest(properties = {
15+
"springdoc.version=v1",
16+
"git.build.time=2025-07-08T12:00:00Z"
17+
})
18+
@AutoConfigureMockMvc
19+
class SpringDocApp245Test {
20+
21+
@Autowired
22+
private MockMvc mockMvc;
23+
24+
@Test
25+
void SpringDocTestApp() throws Exception {
26+
mockMvc.perform(get("/v3/api-docs"))
27+
.andExpect(status().isOk())
28+
.andExpect(jsonPath("$.info.version", is("v1")))
29+
.andExpect(jsonPath("$.info.x-build-time", is("2025-07-08T12:00:00Z")));
30+
}
31+
}

0 commit comments

Comments
 (0)