From feeeab1761d211da36a80972ada0ffb63b524278 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Wed, 30 Oct 2019 13:45:32 +0100 Subject: [PATCH] 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 gh-23896 --- .../datetime/DateFormatterRegistrar.java | 3 +-- .../format/datetime/DateFormattingTests.java | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/format/datetime/DateFormatterRegistrar.java b/spring-context/src/main/java/org/springframework/format/datetime/DateFormatterRegistrar.java index bc2ff0548d..3e7a01b240 100644 --- a/spring-context/src/main/java/org/springframework/format/datetime/DateFormatterRegistrar.java +++ b/spring-context/src/main/java/org/springframework/format/datetime/DateFormatterRegistrar.java @@ -61,14 +61,13 @@ public class DateFormatterRegistrar implements FormatterRegistrar { @Override public void registerFormatters(FormatterRegistry registry) { addDateConverters(registry); - registry.addFormatterForFieldAnnotation(new DateTimeFormatAnnotationFormatterFactory()); - // In order to retain back compatibility we only register Date/Calendar // types when a user defined formatter is specified (see SPR-10105) if (this.dateFormatter != null) { registry.addFormatter(this.dateFormatter); registry.addFormatterForFieldType(Calendar.class, this.dateFormatter); } + registry.addFormatterForFieldAnnotation(new DateTimeFormatAnnotationFormatterFactory()); } /** diff --git a/spring-context/src/test/java/org/springframework/format/datetime/DateFormattingTests.java b/spring-context/src/test/java/org/springframework/format/datetime/DateFormattingTests.java index 7a6cd3df0c..e2cbe51ca3 100644 --- a/spring-context/src/test/java/org/springframework/format/datetime/DateFormattingTests.java +++ b/spring-context/src/test/java/org/springframework/format/datetime/DateFormattingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,7 +46,7 @@ import static org.junit.Assert.*; */ public class DateFormattingTests { - private final FormattingConversionService conversionService = new FormattingConversionService(); + private FormattingConversionService conversionService; private DataBinder binder; @@ -58,6 +58,7 @@ public class DateFormattingTests { } private void setup(DateFormatterRegistrar registrar) { + conversionService = new FormattingConversionService(); DefaultConversionService.addDefaultConverters(conversionService); registrar.registerFormatters(conversionService); @@ -148,6 +149,20 @@ public class DateFormattingTests { assertEquals("10/31/09 1:05", binder.getBindingResult().getFieldValue("dateAnnotatedPattern")); } + @Test + public void testBindDateAnnotatedPatternWithGlobalFormat() { + DateFormatterRegistrar registrar = new DateFormatterRegistrar(); + DateFormatter dateFormatter = new DateFormatter(); + dateFormatter.setIso(ISO.DATE_TIME); + registrar.setFormatter(dateFormatter); + setup(registrar); + MutablePropertyValues propertyValues = new MutablePropertyValues(); + propertyValues.add("dateAnnotatedPattern", "10/31/09 1:05"); + binder.bind(propertyValues); + assertEquals(0, binder.getBindingResult().getErrorCount()); + assertEquals("10/31/09 1:05", binder.getBindingResult().getFieldValue("dateAnnotatedPattern")); + } + @Test public void testBindDateTimeOverflow() { MutablePropertyValues propertyValues = new MutablePropertyValues();