Добавление springdoc в существующий проект Spring MVC REST API вызывает проблемы с пользовательскими преобразователями сообщений. Проект настраивает пользовательские преобразователи сообщений, чтобы установить вывод даты в определенном формате и удалить поля, содержащие null
. Это делается с помощью аннотированного класса @Configuration
, который расширяет WebMvcConfigurationSupport
, который переопределяет configureMessageConverters
и добавляет пользовательский преобразователь, а также преобразователи по умолчанию (addDefaultHttpMessageConverters
).
Чтобы добавить springdoc (версия 1.5.1) в проект, я следовал инструкциям здесь, с небольшим изменением регистрации org.springdoc.webmvc.ui.SwaggerConfig.class
вместо перечисленных org.springdoc.ui.SwaggerConfig.class
, потому что последнего не существует.
Это требует добавления аннотации @EnableWebMvc
, что, в свою очередь, требует реализации WebMvcConfigurer
вместо расширения WebMvcConfigurationSupport
. Используя WebMvcConfigurer
, я не могу добавить конвертеры по умолчанию, используя только пользовательский конвертер, Springdoc JSON экранируется и поэтому недействителен. Если аннотация @EnableWebMvc
не добавлена, страница swagger-ui.html будет недоступна.
Я хочу либо использовать @EnableWebMvc
, реализовать WebMvcConfigurer
и использовать пользовательский конвертер, но предотвратить экранирование Springdoc JSON, добавив конвертеры по умолчанию каким-либо образом или каким-либо другим способом. Или я хочу использовать «старую» конфигурацию, поэтому расширяю WebMvcConfigurationSupport
и не добавляю аннотацию @EnableWebMvc
, а каким-то образом делаю страницу swagger-ui.html доступной.
Как я могу достичь любого из этих вариантов?
Изменить 1
Класс конфигурации был аннотирован с помощью @EnableWebMvc
и реализует WebMvcConfigurer
, таким образом можно получить доступ к странице swagger-ui.html. Преобразователи настраиваются следующим образом:
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
List<MediaType> supportedMediaTypes = new ArrayList<>();
supportedMediaTypes.add(MediaType.APPLICATION_JSON);
for (HttpMessageConverter<?> converter : converters) {
if (converter instanceof MappingJackson2HttpMessageConverter) {
MappingJackson2HttpMessageConverter jsonMessageConverter = (MappingJackson2HttpMessageConverter) converter;
ObjectMapper objectMapper = jsonMessageConverter.getObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.setTimeZone(TimeZone.getTimeZone(timeZone));
jsonMessageConverter.setSupportedMediaTypes(supportedMediaTypes);
break;
}
}
}
Это решение основано на принятом здесь ответе.
Таким образом, все ответы JSON от конечных точек настраиваются, не пропускаются поля null
и используется настроенный часовой пояс, JSON Springdoc также не экранируется.
Я попытался настроить bean-компонент MappingJackson2HttpMessageConverter
и добавить его в список конвертеров, однако Springdoc JSON экранируется, что делает его недействительным.
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(customJsonConverter());
// It's possible to add a converter at a specific index, that to doesn't
// prevent the springdoc JSON from being escaped.
// converters.add(1, customJsonConverter());
}
Редактировать 2
С изменениями, упомянутыми в первом редактировании, все работает нормально. Использование Tomcat 7. Однако приложение будет развернуто с использованием Tomcat 9, что приведет к (несколько неописуемой) ошибке.
[2020-12-15 04:41:42,964] Artifact <artifact-name>:war: Artifact is being deployed, please wait...
15-Dec-2020 16:41:51.791 INFO [RMI TCP Connection(2)-127.0.0.1] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
15-Dec-2020 16:41:52.187 SEVERE [RMI TCP Connection(2)-127.0.0.1] org.apache.tomcat.util.modeler.BaseModelMBean.invoke Exception invoking method [manageApp]
java.lang.IllegalStateException: Error starting child
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:720)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:690)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:705)
at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1727)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:288)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:456)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:405)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:288)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at com.sun.jmx.remote.security.MBeanServerAccessController.invoke(MBeanServerAccessController.java:468)
at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468)
at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309)
at java.security.AccessController.doPrivileged(Native Method)
at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1408)
at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
at sun.rmi.transport.Transport$1.run(Transport.java:200)
at sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:573)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/<application-context>]]
at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:440)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:198)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:717)
... 43 more
Caused by: java.lang.ExceptionInInitializerError
at org.springframework.boot.logging.LoggingSystemFactory.lambda$fromSpringFactories$0(LoggingSystemFactory.java:44)
at org.springframework.boot.logging.DelegatingLoggingSystemFactory.getLoggingSystem(DelegatingLoggingSystemFactory.java:41)
at org.springframework.boot.logging.LoggingSystem.get(LoggingSystem.java:159)
at org.springframework.boot.logging.log4j2.SpringBootConfigurationFactory.getConfiguration(SpringBootConfigurationFactory.java:60)
at org.apache.logging.log4j.core.config.ConfigurationFactory$Factory.getConfiguration(ConfigurationFactory.java:453)
at org.apache.logging.log4j.core.config.ConfigurationFactory$Factory.getConfiguration(ConfigurationFactory.java:385)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:238)
at org.apache.logging.log4j.core.config.Configurator.initialize(Configurator.java:158)
at org.apache.logging.log4j.web.Log4jWebInitializerImpl.initializeNonJndi(Log4jWebInitializerImpl.java:174)
at org.apache.logging.log4j.web.Log4jWebInitializerImpl.start(Log4jWebInitializerImpl.java:112)
at org.apache.logging.log4j.web.Log4jServletContainerInitializer.onStartup(Log4jServletContainerInitializer.java:57)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5128)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
... 44 more
Caused by: java.lang.NullPointerException
at org.springframework.core.io.support.SpringFactoriesLoader.loadSpringFactories(SpringFactoriesLoader.java:126)
at org.springframework.core.io.support.SpringFactoriesLoader.loadFactoryNames(SpringFactoriesLoader.java:122)
at org.springframework.core.io.support.SpringFactoriesLoader.loadFactories(SpringFactoriesLoader.java:98)
at org.springframework.boot.logging.LoggingSystemFactory.lambda$fromSpringFactories$0(LoggingSystemFactory.java:44)
at org.springframework.boot.logging.DelegatingLoggingSystemFactory.getLoggingSystem(DelegatingLoggingSystemFactory.java:41)
at org.springframework.boot.logging.LoggingSystem.get(LoggingSystem.java:159)
at org.springframework.boot.logging.log4j2.SpringBootConfigurationFactory.getConfiguration(SpringBootConfigurationFactory.java:60)
at org.apache.logging.log4j.core.config.ConfigurationFactory$Factory.getConfiguration(ConfigurationFactory.java:453)
at org.apache.logging.log4j.core.config.ConfigurationFactory$Factory.getConfiguration(ConfigurationFactory.java:385)
at org.apache.logging.log4j.core.config.ConfigurationFactory.getConfiguration(ConfigurationFactory.java:260)
at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:615)
at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:636)
at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:231)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:153)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:45)
at org.apache.logging.log4j.LogManager.getContext(LogManager.java:194)
at org.apache.logging.log4j.spi.AbstractLoggerAdapter.getContext(AbstractLoggerAdapter.java:121)
at org.apache.logging.log4j.jcl.LogAdapter.getContext(LogAdapter.java:39)
at org.apache.logging.log4j.spi.AbstractLoggerAdapter.getLogger(AbstractLoggerAdapter.java:46)
at org.apache.logging.log4j.jcl.LogFactoryImpl.getInstance(LogFactoryImpl.java:40)
at org.apache.logging.log4j.jcl.LogFactoryImpl.getInstance(LogFactoryImpl.java:55)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:685)
at org.springframework.core.io.support.SpringFactoriesLoader.<clinit>(SpringFactoriesLoader.java:71)
... 57 more
15-Dec-2020 16:41:52.189 SEVERE [RMI TCP Connection(2)-127.0.0.1] org.apache.tomcat.util.modeler.BaseModelMBean.invoke Exception invoking method [createStandardContext]
javax.management.RuntimeOperationsException: Exception invoking method [manageApp]
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:297)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:456)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:405)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:288)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at com.sun.jmx.remote.security.MBeanServerAccessController.invoke(MBeanServerAccessController.java:468)
at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468)
at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309)
at java.security.AccessController.doPrivileged(Native Method)
at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1408)
at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
at sun.rmi.transport.Transport$1.run(Transport.java:200)
at sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:573)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalStateException: Error starting child
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:720)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:690)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:705)
at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1727)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:288)
... 35 more
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/<application-context>]]
at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:440)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:198)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:717)
... 43 more
Caused by: java.lang.ExceptionInInitializerError
at org.springframework.boot.logging.LoggingSystemFactory.lambda$fromSpringFactories$0(LoggingSystemFactory.java:44)
at org.springframework.boot.logging.DelegatingLoggingSystemFactory.getLoggingSystem(DelegatingLoggingSystemFactory.java:41)
at org.springframework.boot.logging.LoggingSystem.get(LoggingSystem.java:159)
at org.springframework.boot.logging.log4j2.SpringBootConfigurationFactory.getConfiguration(SpringBootConfigurationFactory.java:60)
at org.apache.logging.log4j.core.config.ConfigurationFactory$Factory.getConfiguration(ConfigurationFactory.java:453)
at org.apache.logging.log4j.core.config.ConfigurationFactory$Factory.getConfiguration(ConfigurationFactory.java:385)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:238)
at org.apache.logging.log4j.core.config.Configurator.initialize(Configurator.java:158)
at org.apache.logging.log4j.web.Log4jWebInitializerImpl.initializeNonJndi(Log4jWebInitializerImpl.java:174)
at org.apache.logging.log4j.web.Log4jWebInitializerImpl.start(Log4jWebInitializerImpl.java:112)
at org.apache.logging.log4j.web.Log4jServletContainerInitializer.onStartup(Log4jServletContainerInitializer.java:57)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5128)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
... 44 more
Caused by: java.lang.NullPointerException
at org.springframework.core.io.support.SpringFactoriesLoader.loadSpringFactories(SpringFactoriesLoader.java:126)
at org.springframework.core.io.support.SpringFactoriesLoader.loadFactoryNames(SpringFactoriesLoader.java:122)
at org.springframework.core.io.support.SpringFactoriesLoader.loadFactories(SpringFactoriesLoader.java:98)
at org.springframework.boot.logging.LoggingSystemFactory.lambda$fromSpringFactories$0(LoggingSystemFactory.java:44)
at org.springframework.boot.logging.DelegatingLoggingSystemFactory.getLoggingSystem(DelegatingLoggingSystemFactory.java:41)
at org.springframework.boot.logging.LoggingSystem.get(LoggingSystem.java:159)
at org.springframework.boot.logging.log4j2.SpringBootConfigurationFactory.getConfiguration(SpringBootConfigurationFactory.java:60)
at org.apache.logging.log4j.core.config.ConfigurationFactory$Factory.getConfiguration(ConfigurationFactory.java:453)
at org.apache.logging.log4j.core.config.ConfigurationFactory$Factory.getConfiguration(ConfigurationFactory.java:385)
at org.apache.logging.log4j.core.config.ConfigurationFactory.getConfiguration(ConfigurationFactory.java:260)
at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:615)
at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:636)
at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:231)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:153)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:45)
at org.apache.logging.log4j.LogManager.getContext(LogManager.java:194)
at org.apache.logging.log4j.spi.AbstractLoggerAdapter.getContext(AbstractLoggerAdapter.java:121)
at org.apache.logging.log4j.jcl.LogAdapter.getContext(LogAdapter.java:39)
at org.apache.logging.log4j.spi.AbstractLoggerAdapter.getLogger(AbstractLoggerAdapter.java:46)
at org.apache.logging.log4j.jcl.LogFactoryImpl.getInstance(LogFactoryImpl.java:40)
at org.apache.logging.log4j.jcl.LogFactoryImpl.getInstance(LogFactoryImpl.java:55)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:685)
at org.springframework.core.io.support.SpringFactoriesLoader.<clinit>(SpringFactoriesLoader.java:71)
... 57 more
[2020-12-15 04:41:52,197] Artifact <artifact-name>:war: Error during artifact deployment. See server log for details.
15-Dec-2020 16:41:52.702 INFO [Catalina-utility-2] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/Users/dopheidp/Programs/apache-tomcat-9.0.37/webapps/manager]
15-Dec-2020 16:41:52.775 INFO [Catalina-utility-2] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
15-Dec-2020 16:41:52.794 INFO [Catalina-utility-2] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/Users/dopheidp/Programs/apache-tomcat-9.0.37/webapps/manager] has finished in [92] ms
Имя артефакта и контекст приложения были заменены на и, соответственно, в целях безопасности.
Исключение в Tomcat 9, по-видимому, вызвано зависимостью springdoc и/или Spring Boot, которая была добавлена в проект. При понижении версии Springdoc с версии 1.5.1
до 1.4.8
и Spring Boot с 2.4.0
до 2.3.5.RELEASE
все отлично работает под Tomcat 9 (и Tomcat 7).
Springdoc был добавлен в проект Spring MVC с использованием инструкций с веб-сайта sprindoc. Это означало добавление аннотации @EnableWebMvc
и изменение класса конфигурации, расширяющего WebMvcConfigurationSupport
для реализации WebMvcConfigurer
. Так
public class WebMvcConfig extends WebMvcConfigurationSupport { ... }
становится
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurationSupport { ... }
Эти изменения приводят к сбою преобразователей сообщений, которые используются для глобальной настройки ответов JSON. Чтобы решить эту проблему, предыдущие методы, используемые для настройки преобразователей сообщений, удалены.
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(jsonConverter());
addDefaultHttpMessageConverters(converters);
}
@Bean
public MappingJackson2HttpMessageConverter jsonConverter() {
List<MediaType> supportedMediaTypes = new ArrayList<>();
supportedMediaTypes.add(MediaType.APPLICATION_JSON);
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.serializationInclusion(JsonInclude.Include.NON_NULL);
builder.timeZone(TimeZone.getTimeZone(timeZone));
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(builder.build());
jsonConverter.setSupportedMediaTypes(supportedMediaTypes);
return jsonConverter;
}
И заменен следующим методом. Другие способы настройки преобразователей сообщений, похоже, не работают, см. вопрос о вариантах конфигурации, которые были опробованы.
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
for (HttpMessageConverter<?> converter : converters) {
if (converter instanceof MappingJackson2HttpMessageConverter) {
MappingJackson2HttpMessageConverter jsonMessageConverter = (MappingJackson2HttpMessageConverter) converter;
ObjectMapper objectMapper = jsonMessageConverter.getObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.setTimeZone(TimeZone.getTimeZone(timeZone));
jsonMessageConverter.setSupportedMediaTypes(supportedMediaTypes);
break;
}
}
}
В настоящее время проект использует версию Springdoc 1.4.8
и версию Spring Boot 2.3.5.RELEASE
в качестве зависимостей, использование последних доступных версий Springdoc 1.5.1
и Spring Boot 2.4.0
на момент написания этой статьи приводит к исключению в Tomcat 9, препятствующему запуску проекта.