mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-22 05:49:04 +00:00
Avoid duplicate date-related converters registration
Prior to this commit, `DefaultFormattingConversionService` would register converters with both `DateTimeFormatterRegistrar` and `DateFormatterRegistrar`, the former also registering the legace date converters that the latter contributes. While we cannot change the behavior for `DateTimeFormatterRegistrar` or `DateFormatterRegistrar` because of their public contract, we can update the `DefaultFormattingConversionService` to not use `DateFormatterRegistrar` and register manually the annotation support that it contributes. Closes gh-36951
This commit is contained in:
+5
-4
@@ -20,7 +20,7 @@ import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.format.FormatterRegistry;
|
||||
import org.springframework.format.datetime.DateFormatterRegistrar;
|
||||
import org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory;
|
||||
import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
|
||||
import org.springframework.format.number.NumberFormatAnnotationFormatterFactory;
|
||||
import org.springframework.format.number.money.CurrencyUnitFormatter;
|
||||
@@ -115,11 +115,12 @@ public class DefaultFormattingConversionService extends FormattingConversionServ
|
||||
|
||||
// Default handling of date-time values
|
||||
|
||||
// just handling JSR-310 specific date and time types
|
||||
// Handling of JSR-310 specific date and time types, along with the legacy
|
||||
// Date/Calendar/Long converters (see DateTimeConverters).
|
||||
new DateTimeFormatterRegistrar().registerFormatters(formatterRegistry);
|
||||
|
||||
// regular DateFormat-based Date, Calendar, Long converters
|
||||
new DateFormatterRegistrar().registerFormatters(formatterRegistry);
|
||||
// Support for the @DateTimeFormat annotation on legacy Date/Calendar fields
|
||||
formatterRegistry.addFormatterForFieldAnnotation(new DateTimeFormatAnnotationFormatterFactory());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+35
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.format.support;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@@ -30,6 +32,7 @@ import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConverterFactory;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.format.Formatter;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.format.number.NumberStyleFormatter;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -176,6 +179,28 @@ class FormattingConversionServiceTests {
|
||||
assertThat(formattingService.convert("1", Integer.class)).isEqualTo(Integer.valueOf(1));
|
||||
}
|
||||
|
||||
@Test // gh-36951
|
||||
void defaultFormattingConversionServiceRegistersLegacyDateConvertersOnlyOnce() {
|
||||
DefaultFormattingConversionService defaultService = new DefaultFormattingConversionService();
|
||||
String convertersDescription = defaultService.toString();
|
||||
assertThat(convertersDescription)
|
||||
.containsOnlyOnce("DateFormatterRegistrar$DateToLongConverter")
|
||||
.containsOnlyOnce("DateFormatterRegistrar$CalendarToDateConverter");
|
||||
}
|
||||
|
||||
@Test // gh-36951
|
||||
void defaultFormattingConversionServiceStillAppliesDateTimeFormatAnnotationToLegacyDateAndCalendarFields() throws Exception {
|
||||
DefaultFormattingConversionService defaultService = new DefaultFormattingConversionService();
|
||||
TypeDescriptor dateDescriptor = new TypeDescriptor(AnnotatedDateBean.class.getDeclaredField("date"));
|
||||
TypeDescriptor calendarDescriptor = new TypeDescriptor(AnnotatedDateBean.class.getDeclaredField("calendar"));
|
||||
|
||||
Date date = (Date) defaultService.convert("2026-09-19", TypeDescriptor.valueOf(String.class), dateDescriptor);
|
||||
Calendar calendar = (Calendar) defaultService.convert("2026-09-19", TypeDescriptor.valueOf(String.class), calendarDescriptor);
|
||||
|
||||
assertThat(defaultService.convert(date, dateDescriptor, TypeDescriptor.valueOf(String.class))).isEqualTo("2026-09-19");
|
||||
assertThat(defaultService.convert(calendar, calendarDescriptor, TypeDescriptor.valueOf(String.class))).isEqualTo("2026-09-19");
|
||||
}
|
||||
|
||||
|
||||
static class NullReturningFormatter implements Formatter<Integer> {
|
||||
|
||||
@@ -214,4 +239,14 @@ class FormattingConversionServiceTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class AnnotatedDateBean {
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
private Date date;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
private Calendar calendar;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user