Skip to content

Commit cf1fbcd

Browse files
bclozelpull[bot]
authored andcommitted
Reorder date formatting converter in registrar
Prior to this commit, the `DateFormatterRegistrar` would register the annotation-based formatter before the pattern-based formatter. This would create an issue when an application tries to convert a `String` to an annotated `@DateTimeFormat Date`: since the converters are considered in reversed order of registration in `GenericConversionServicei#ConvertersForPair`, the pattern-based variant would always be considered before the annotation-based variant, overriding the developer's opinion. This commit aligns the `DateFormatterRegistrar` with the `DateTimeFormatterRegistrar` and registers the annotation-based variant last. Closes spring-projectsgh-23893
1 parent 8562972 commit cf1fbcd

File tree

2 files changed

+36
-22
lines changed

2 files changed

+36
-22
lines changed

spring-context/src/main/java/org/springframework/format/datetime/DateFormatterRegistrar.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,13 @@ public void setFormatter(DateFormatter dateFormatter) {
6161
@Override
6262
public void registerFormatters(FormatterRegistry registry) {
6363
addDateConverters(registry);
64-
registry.addFormatterForFieldAnnotation(new DateTimeFormatAnnotationFormatterFactory());
65-
6664
// In order to retain back compatibility we only register Date/Calendar
6765
// types when a user defined formatter is specified (see SPR-10105)
6866
if (this.dateFormatter != null) {
6967
registry.addFormatter(this.dateFormatter);
7068
registry.addFormatterForFieldType(Calendar.class, this.dateFormatter);
7169
}
70+
registry.addFormatterForFieldAnnotation(new DateTimeFormatAnnotationFormatterFactory());
7271
}
7372

7473
/**

spring-context/src/test/java/org/springframework/format/datetime/DateFormattingTests.java

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,19 @@
4545
*/
4646
public class DateFormattingTests {
4747

48-
private final FormattingConversionService conversionService = new FormattingConversionService();
48+
private FormattingConversionService conversionService;
4949

5050
private DataBinder binder;
5151

5252

5353
@BeforeEach
54-
public void setup() {
54+
void setup() {
5555
DateFormatterRegistrar registrar = new DateFormatterRegistrar();
5656
setup(registrar);
5757
}
5858

5959
private void setup(DateFormatterRegistrar registrar) {
60+
conversionService = new FormattingConversionService();
6061
DefaultConversionService.addDefaultConverters(conversionService);
6162
registrar.registerFormatters(conversionService);
6263

@@ -69,13 +70,13 @@ private void setup(DateFormatterRegistrar registrar) {
6970
}
7071

7172
@AfterEach
72-
public void tearDown() {
73+
void tearDown() {
7374
LocaleContextHolder.setLocale(null);
7475
}
7576

7677

7778
@Test
78-
public void testBindLong() {
79+
void testBindLong() {
7980
MutablePropertyValues propertyValues = new MutablePropertyValues();
8081
propertyValues.add("millis", "1256961600");
8182
binder.bind(propertyValues);
@@ -84,7 +85,7 @@ public void testBindLong() {
8485
}
8586

8687
@Test
87-
public void testBindLongAnnotated() {
88+
void testBindLongAnnotated() {
8889
MutablePropertyValues propertyValues = new MutablePropertyValues();
8990
propertyValues.add("millisAnnotated", "10/31/09");
9091
binder.bind(propertyValues);
@@ -93,7 +94,7 @@ public void testBindLongAnnotated() {
9394
}
9495

9596
@Test
96-
public void testBindCalendarAnnotated() {
97+
void testBindCalendarAnnotated() {
9798
MutablePropertyValues propertyValues = new MutablePropertyValues();
9899
propertyValues.add("calendarAnnotated", "10/31/09");
99100
binder.bind(propertyValues);
@@ -102,7 +103,7 @@ public void testBindCalendarAnnotated() {
102103
}
103104

104105
@Test
105-
public void testBindDateAnnotated() {
106+
void testBindDateAnnotated() {
106107
MutablePropertyValues propertyValues = new MutablePropertyValues();
107108
propertyValues.add("dateAnnotated", "10/31/09");
108109
binder.bind(propertyValues);
@@ -111,15 +112,15 @@ public void testBindDateAnnotated() {
111112
}
112113

113114
@Test
114-
public void testBindDateArray() {
115+
void testBindDateArray() {
115116
MutablePropertyValues propertyValues = new MutablePropertyValues();
116117
propertyValues.add("dateAnnotated", new String[]{"10/31/09 12:00 PM"});
117118
binder.bind(propertyValues);
118119
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
119120
}
120121

121122
@Test
122-
public void testBindDateAnnotatedWithError() {
123+
void testBindDateAnnotatedWithError() {
123124
MutablePropertyValues propertyValues = new MutablePropertyValues();
124125
propertyValues.add("dateAnnotated", "Oct X31, 2009");
125126
binder.bind(propertyValues);
@@ -129,7 +130,7 @@ public void testBindDateAnnotatedWithError() {
129130

130131
@Test
131132
@Disabled
132-
public void testBindDateAnnotatedWithFallbackError() {
133+
void testBindDateAnnotatedWithFallbackError() {
133134
// TODO This currently passes because of the Date(String) constructor fallback is used
134135
MutablePropertyValues propertyValues = new MutablePropertyValues();
135136
propertyValues.add("dateAnnotated", "Oct 031, 2009");
@@ -139,7 +140,7 @@ public void testBindDateAnnotatedWithFallbackError() {
139140
}
140141

141142
@Test
142-
public void testBindDateAnnotatedPattern() {
143+
void testBindDateAnnotatedPattern() {
143144
MutablePropertyValues propertyValues = new MutablePropertyValues();
144145
propertyValues.add("dateAnnotatedPattern", "10/31/09 1:05");
145146
binder.bind(propertyValues);
@@ -148,15 +149,29 @@ public void testBindDateAnnotatedPattern() {
148149
}
149150

150151
@Test
151-
public void testBindDateTimeOverflow() {
152+
void testBindDateAnnotatedPatternWithGlobalFormat() {
153+
DateFormatterRegistrar registrar = new DateFormatterRegistrar();
154+
DateFormatter dateFormatter = new DateFormatter();
155+
dateFormatter.setIso(ISO.DATE_TIME);
156+
registrar.setFormatter(dateFormatter);
157+
setup(registrar);
158+
MutablePropertyValues propertyValues = new MutablePropertyValues();
159+
propertyValues.add("dateAnnotatedPattern", "10/31/09 1:05");
160+
binder.bind(propertyValues);
161+
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
162+
assertThat(binder.getBindingResult().getFieldValue("dateAnnotatedPattern")).isEqualTo("10/31/09 1:05");
163+
}
164+
165+
@Test
166+
void testBindDateTimeOverflow() {
152167
MutablePropertyValues propertyValues = new MutablePropertyValues();
153168
propertyValues.add("dateAnnotatedPattern", "02/29/09 12:00 PM");
154169
binder.bind(propertyValues);
155170
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(1);
156171
}
157172

158173
@Test
159-
public void testBindISODate() {
174+
void testBindISODate() {
160175
MutablePropertyValues propertyValues = new MutablePropertyValues();
161176
propertyValues.add("isoDate", "2009-10-31");
162177
binder.bind(propertyValues);
@@ -165,7 +180,7 @@ public void testBindISODate() {
165180
}
166181

167182
@Test
168-
public void testBindISOTime() {
183+
void testBindISOTime() {
169184
MutablePropertyValues propertyValues = new MutablePropertyValues();
170185
propertyValues.add("isoTime", "12:00:00.000-05:00");
171186
binder.bind(propertyValues);
@@ -174,7 +189,7 @@ public void testBindISOTime() {
174189
}
175190

176191
@Test
177-
public void testBindISODateTime() {
192+
void testBindISODateTime() {
178193
MutablePropertyValues propertyValues = new MutablePropertyValues();
179194
propertyValues.add("isoDateTime", "2009-10-31T12:00:00.000-08:00");
180195
binder.bind(propertyValues);
@@ -183,7 +198,7 @@ public void testBindISODateTime() {
183198
}
184199

185200
@Test
186-
public void testBindNestedDateAnnotated() {
201+
void testBindNestedDateAnnotated() {
187202
MutablePropertyValues propertyValues = new MutablePropertyValues();
188203
propertyValues.add("children[0].dateAnnotated", "10/31/09");
189204
binder.bind(propertyValues);
@@ -192,15 +207,15 @@ public void testBindNestedDateAnnotated() {
192207
}
193208

194209
@Test
195-
public void dateToStringWithoutGlobalFormat() {
210+
void dateToStringWithoutGlobalFormat() {
196211
Date date = new Date();
197212
Object actual = this.conversionService.convert(date, TypeDescriptor.valueOf(Date.class), TypeDescriptor.valueOf(String.class));
198213
String expected = date.toString();
199214
assertThat(actual).isEqualTo(expected);
200215
}
201216

202217
@Test
203-
public void dateToStringWithGlobalFormat() {
218+
void dateToStringWithGlobalFormat() {
204219
DateFormatterRegistrar registrar = new DateFormatterRegistrar();
205220
registrar.setFormatter(new DateFormatter());
206221
setup(registrar);
@@ -212,14 +227,14 @@ public void dateToStringWithGlobalFormat() {
212227

213228
@Test // SPR-10105
214229
@SuppressWarnings("deprecation")
215-
public void stringToDateWithoutGlobalFormat() {
230+
void stringToDateWithoutGlobalFormat() {
216231
String string = "Sat, 12 Aug 1995 13:30:00 GM";
217232
Date date = this.conversionService.convert(string, Date.class);
218233
assertThat(date).isEqualTo(new Date(string));
219234
}
220235

221236
@Test // SPR-10105
222-
public void stringToDateWithGlobalFormat() {
237+
void stringToDateWithGlobalFormat() {
223238
DateFormatterRegistrar registrar = new DateFormatterRegistrar();
224239
DateFormatter dateFormatter = new DateFormatter();
225240
dateFormatter.setIso(ISO.DATE_TIME);

0 commit comments

Comments
 (0)