springdoc-openapi
springdoc-openapi copied to clipboard
Custom ModelResolver and TypeNameResolver results in unexpected behaviour
Hi!
I am using:
- Spring Boot 3.2.4
- Java 21
- springdoc-openapi-starter-webmvc-ui 2.5.0
When implementing a custom ModelResolver
and TypeNameResolver
the behaviour of entities wrapped in a ResponseEntity
changes.
Here is my implementation:
@Configuration
public class SwaggerAutoConfiguration {
@Bean
public CustomConverter customConverter(ObjectMapper objectMapper) {
return new CustomConverter(objectMapper);
}
static class CustomTypeNameResolver extends TypeNameResolver {
public CustomTypeNameResolver() {
setUseFqn(true);
}
}
public static class CustomConverter extends ModelResolver {
public CustomConverter(ObjectMapper mapper) {
super(mapper, new CustomTypeNameResolver());
}
}
}
I am using the above setup because I will have logic to modify the model names.
I would expect the above only to set useFqn
to true, and the rest would stay the same. However that does not seem like the case for entities wrapped a ResponseEntity
. Below is an example.
@Operation(summary = "...")
@ApiResponses(value = {
@ApiResponse(
responseCode = "200"
),
@ApiResponse(
responseCode = "207",
description = "Partial success"
),
@ApiResponse(
responseCode = "409",
description = "Failure"
)
})
@PostMapping(path = AUTHENTICATE_PAYMENT)
public ResponseEntity<AuthenticatePaymentResponse> authenticatePayment(
@Valid @RequestBody AuthenticatePaymentRequest authenticatePaymentRequest,
SomeOtherParameters someOtherParameters
) {
...
}
After adding the configuration, the response body changes in Swagger for all defined ApiResponses on the endpoint like so:
{
"headers": {
"acceptLanguage": [
{
"range": "string",
"weight": 0
}
],
"acceptPatch": [
{
"type": "string",
"subtype": "string",
"parameters": {
"additionalProp1": "string",
"additionalProp2": "string",
"additionalProp3": "string"
},
"qualityValue": 0,
"wildcardType": true,
"wildcardSubtype": true,
"subtypeSuffix": "string",
"charset": {
"registered": true
},
"concrete": true
}
],
"accessControlAllowCredentials": true,
"accessControlExposeHeaders": [
"string"
],
"accessControlRequestHeaders": [
"string"
],
"accessControlRequestMethod": {},
"acceptLanguageAsLocales": [
{
"language": "string",
"displayName": "string",
"country": "string",
"variant": "string",
"script": "string",
"unicodeLocaleAttributes": [
"string"
],
"unicodeLocaleKeys": [
"string"
],
"displayLanguage": "string",
"displayScript": "string",
"displayCountry": "string",
"displayVariant": "string",
"extensionKeys": [
"string"
],
"iso3Language": "string",
"iso3Country": "string"
}
],
"accessControlAllowHeaders": [
"string"
],
"accessControlAllowMethods": [
{}
],
"accessControlAllowOrigin": "string",
"accessControlMaxAge": 0,
"acceptCharset": [
{
"registered": true
}
],
"connection": [
"string"
],
"ifNoneMatch": [
"string"
],
"ifUnmodifiedSince": 0,
"etag": "string",
"expires": 0,
"ifMatch": [
"string"
],
"allow": [
{}
],
"accept": [
{
"type": "string",
"subtype": "string",
"parameters": {
"additionalProp1": "string",
"additionalProp2": "string",
"additionalProp3": "string"
},
"qualityValue": 0,
"wildcardType": true,
"wildcardSubtype": true,
"subtypeSuffix": "string",
"charset": {
"registered": true
},
"concrete": true
}
],
"origin": "string",
"pragma": "string",
"range": [
{}
],
"upgrade": "string",
"vary": [
"string"
],
"contentDisposition": {
"type": "string",
"name": "string",
"filename": "string",
"charset": {
"registered": true
},
"size": 0,
"creationDate": "2024-04-15T19:18:37.770Z",
"modificationDate": "2024-04-15T19:18:37.770Z",
"readDate": "2024-04-15T19:18:37.770Z",
"attachment": true,
"formData": true,
"inline": true
},
"contentLanguage": {
"language": "string",
"displayName": "string",
"country": "string",
"variant": "string",
"script": "string",
"unicodeLocaleAttributes": [
"string"
],
"unicodeLocaleKeys": [
"string"
],
"displayLanguage": "string",
"displayScript": "string",
"displayCountry": "string",
"displayVariant": "string",
"extensionKeys": [
"string"
],
"iso3Language": "string",
"iso3Country": "string"
},
"cacheControl": "string",
"host": {
"hostString": "string",
"address": {
"hostAddress": "string",
"address": [
"string"
],
"hostName": "string",
"linkLocalAddress": true,
"multicastAddress": true,
"anyLocalAddress": true,
"loopbackAddress": true,
"siteLocalAddress": true,
"mcglobal": true,
"mcnodeLocal": true,
"mclinkLocal": true,
"mcsiteLocal": true,
"mcorgLocal": true,
"canonicalHostName": "string"
},
"port": 0,
"unresolved": true,
"hostName": "string"
},
"location": "string",
"contentType": {
"type": "string",
"subtype": "string",
"parameters": {
"additionalProp1": "string",
"additionalProp2": "string",
"additionalProp3": "string"
},
"qualityValue": 0,
"wildcardType": true,
"wildcardSubtype": true,
"subtypeSuffix": "string",
"charset": {
"registered": true
},
"concrete": true
},
"contentLength": 0,
"ifModifiedSince": 0,
"empty": true,
"lastModified": 0,
"date": 0,
"additionalProp1": [
"string"
],
"additionalProp2": [
"string"
],
"additionalProp3": [
"string"
]
},
"body": <my-model>,
"statusCodeValue": 0,
"statusCode": {
"is1xxInformational": true,
"is2xxSuccessful": true,
"is3xxRedirection": true,
"is4xxClientError": true,
"is5xxServerError": true,
"error": true
}
}
I would expect the defined configuration to work exactly the same as setting the below properties:
springdoc:
use-fqn: true
Am I missing something here?