Я обновляю наше приложение с Spring Boot 2.7.10 до 3.0.5.
Я также запускаю его из IDE на встроенном Tomcat и внешнем Tomcat (версия 9 для Spring Boot 2.7.x). Сейчас я использую Tomcat 10.1.7 и Jackson 2.14.2.
Он по-прежнему работает на встроенном Tomcat, но не на внешнем Tomcat 10. Я получаю:
Failed to bind properties under 'my-configuration.object-mapper.serializer-provider.generator.write-capabilities' to com.fasterxml.jackson.core.util.JacksonFeatureSet<com.fasterxml.jackson.core.StreamWriteCapability>:
Reason: org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'my-configuration.object-mapper.serializer-provider.generator.write-capabilities' to com.fasterxml.jackson.core.util.JacksonFeatureSet<com.fasterxml.jackson.core.StreamWriteCapability>
С использованием
@ConfigurationProperties(prefix = "my-configuration")
@Getter
@Setter
public class MyConfiguration {
private ObjectMapper objectMapper;
}
Я могу подавить ошибку, указав ignoreInvalidFields
, но убедиться, что это правильное решение.
@ConfigurationProperties(prefix = "my-configuration", ignoreInvalidFields = true)
Несомненно, мне нужно реорганизовать наши классы конфигурации, но все же я хотел бы понять, что происходит и почему происходит сбой после Spring Boot 3 и только внешнего Tomcat.
Трассировки стека
Caused by: org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'my-configuration.object-mapper.serializer-provider.generator.write-capabilities' to com.fasterxml.jackson.core.util.JacksonFeatureSet<com.fasterxml.jackson.core.StreamWriteCapability>
at org.springframework.boot.context.properties.bind.Binder.handleBindError(Binder.java:387)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:347)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$4(Binder.java:472)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:98)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:86)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:62)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:476)
at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:590)
at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:576)
at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:474)
at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:414)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:343)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$4(Binder.java:472)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:98)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:86)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:62)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:476)
at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:590)
at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:576)
at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:474)
at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:414)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:343)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$4(Binder.java:472)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:98)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:86)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:62)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:476)
at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:590)
at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:576)
at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:474)
at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:414)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:343)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$4(Binder.java:472)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:98)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:86)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:62)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:476)
at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:590)
at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:576)
at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:474)
at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:414)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:343)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$4(Binder.java:472)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:98)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:86)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:62)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:476)
at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:590)
at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:576)
at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:474)
at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:414)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:343)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:332)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:262)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:249)
at org.springframework.boot.context.properties.ConfigurationPropertiesBinder.bind(ConfigurationPropertiesBinder.java:93)
at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.bind(ConfigurationPropertiesBindingPostProcessor.java:96)
... 121 more
Caused by: java.lang.IllegalStateException: Unable to get value for property write-capabilities
at org.springframework.boot.context.properties.bind.JavaBeanBinder$BeanProperty.lambda$getValue$0(JavaBeanBinder.java:360)
at org.springframework.boot.context.properties.bind.DefaultBindConstructorProvider.getBindConstructor(DefaultBindConstructorProvider.java:46)
at org.springframework.boot.context.properties.bind.ValueObjectBinder$ValueObject.get(ValueObjectBinder.java:190)
at org.springframework.boot.context.properties.bind.ValueObjectBinder.bind(ValueObjectBinder.java:67)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:476)
at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:590)
at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:576)
at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:474)
at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:414)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:343)
... 176 more
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.fasterxml.jackson.core.JsonGenerator]: Is it an abstract class?
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:215)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:153)
at org.springframework.boot.context.properties.bind.JavaBeanBinder$Bean.lambda$getSupplier$0(JavaBeanBinder.java:217)
at org.springframework.boot.context.properties.bind.JavaBeanBinder$BeanSupplier.get(JavaBeanBinder.java:279)
at org.springframework.boot.context.properties.bind.JavaBeanBinder$BeanProperty.lambda$getValue$0(JavaBeanBinder.java:357)
... 185 more
Caused by: java.lang.InstantiationException
at java.base/jdk.internal.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:48)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:198)
... 189 more
Устаревшая конфигурация остальных клиентов. В любом случае, главный вопрос в том, почему встроенный кот ведет себя не так, как внешний?
Если вы не создадите свой собственный ObjectMapper
, это повлияет на глобальный. Почему он другой, сказать сложно, это та же версия, что и встроенная? Пожалуйста, включите полную трассировку стека вместо фрагмента.
Добавлена трассировка стека. Несомненно, мне нужно реорганизовать наши классы конфигурации, но все же я хотел бы понять, что происходит и почему происходит сбой после Spring Boot 3 и только внешнего Tomcat.
Существуют ли какие-либо дополнительные библиотеки, входящие в состав установки yur tomcat, которые мешают добавленным зависимостям Spring?
Это свежий новый Tomcat. Интересно, отличается ли загрузка классов. Я собирался сообщить об этом команде Spring, но когда я попробовал базовый проект, я не смог его воспроизвести. Я должен копнуть глубже, какая зависимость вызывает такое столкновение.
Может быть проблема с зависимостями, что при построении войны конфликтующая зависимость имеет приоритет над другой при запуске в командной строке. Может быть разница в ОС (Windows, Linux и Mac иногда имеют разные порядки разрешения для пути к классу).
Наконец, у меня есть минимальный проект для воспроизведения. Я открыл вопрос github.com/spring-projects/spring-boot/issues/35091
Как объясняется в выпуске https://github.com/spring-projects/spring-boot/issues/35091#issuecomment-1516051146 основная причина в том, что на внешнем Tomcat включен JNDI.
Это влияет на привязку свойства. JNDI не позволяет перечислять все свойства, которые он содержит, поэтому вместо того, чтобы находить все свойства и привязывать их к целям, Spring вместо этого должен запрашивать все цели, какие свойства у них есть, а затем пытаться их связать. Это когда ObjectMapper
вызывает проблему.
Что вы пытаетесь сделать? Почему бы вам просто не использовать свойства
spring.jackson
для настройки привязки?