diff --git a/springdoc-openapi-common/src/main/java/org/springdoc/core/converters/ModelConverterRegistrar.java b/springdoc-openapi-common/src/main/java/org/springdoc/core/converters/ModelConverterRegistrar.java index c46466767..6cf3ef69e 100644 --- a/springdoc-openapi-common/src/main/java/org/springdoc/core/converters/ModelConverterRegistrar.java +++ b/springdoc-openapi-common/src/main/java/org/springdoc/core/converters/ModelConverterRegistrar.java @@ -20,21 +20,54 @@ package org.springdoc.core.converters; +import java.lang.reflect.Field; import java.util.List; +import java.util.Optional; import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverters; +import org.apache.commons.lang3.reflect.FieldUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Wrapper for model converters to only register converters once */ public class ModelConverterRegistrar { + private static final ModelConverters modelConvertersInstance = ModelConverters.getInstance(); + private static final Logger LOGGER = LoggerFactory.getLogger(ModelConverterRegistrar.class); + /** * @param modelConverters spring registered model converter beans which have to be * registered in {@link ModelConverters} instance */ public ModelConverterRegistrar(List modelConverters) { - modelConverters.forEach(ModelConverters.getInstance()::addConverter); + for (ModelConverter modelConverter : modelConverters) { + Optional registeredConverterOptional = getRegisteredConverterSameAs(modelConverter); + registeredConverterOptional.ifPresent(modelConvertersInstance::removeConverter); + modelConvertersInstance.addConverter(modelConverter); + } + } + + private Optional getRegisteredConverterSameAs(ModelConverter modelConverter) { + try { + Field convertersField = FieldUtils.getDeclaredField(ModelConverters.class, "converters", true); + List modelConverters = (List) convertersField.get(modelConvertersInstance); + return modelConverters.stream() + .filter(registeredModelConverter -> isSameConverter(registeredModelConverter, modelConverter)) + .findFirst(); + } + catch (IllegalAccessException exception) { + LOGGER.error(exception.getMessage(), exception); + throw new RuntimeException(exception); + } + } + + private boolean isSameConverter(ModelConverter modelConverter1, ModelConverter modelConverter2) { + // comparing by the converter type + Class modelConverter1Class = modelConverter1.getClass(); + Class modelConverter2Class = modelConverter2.getClass(); + return modelConverter1Class.equals(modelConverter2Class); } } diff --git a/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/AbstractSpringDocTest.java b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/AbstractSpringDocTest.java index a01c13ab2..f5aef11e3 100644 --- a/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/AbstractSpringDocTest.java +++ b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/AbstractSpringDocTest.java @@ -22,10 +22,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.List; -import io.swagger.v3.core.converter.ModelConverter; -import io.swagger.v3.core.converter.ModelConverters; import nonapi.io.github.classgraph.utils.FileUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; @@ -57,8 +54,6 @@ public abstract class AbstractSpringDocTest { public static String className; - private static List modelConverters; - @Autowired protected MockMvc mockMvc; @@ -75,16 +70,10 @@ public static String getContent(String fileName) throws Exception { @AfterAll public static void afterClass() { - modelConverters.forEach(ModelConverters.getInstance()::removeConverter); System.clearProperty("spring.hateoas.use-hal-as-default-json-media-type"); getConfig().replaceWithClass(org.springframework.data.domain.Pageable.class, Pageable.class); } - @Autowired - private void setModelConverters(List modelConverters) { - AbstractSpringDocTest.modelConverters = modelConverters; - } - @Test public void testApp() throws Exception { className = getClass().getSimpleName();