Skip to content

Commit

Permalink
Retain root cause for parsing patterns in @DateTimeFormat
Browse files Browse the repository at this point in the history
The support for fallback parsing patterns in @DateTimeFormat introduced
in spring-projectsgh-20292 introduced a regression in that the original cause of the
parsing exception was no longer retained.

This commit ensures that the original DateTimeParseException is set as
the cause for any newly created DateTimeParseException, thereby
retaining the original exception as the root cause.

Closes spring-projectsgh-26777
  • Loading branch information
sbrannen authored and Zoran0104 committed Aug 20, 2021
1 parent 50acabc commit d168748
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 3 deletions.
Expand Up @@ -101,7 +101,7 @@ public TemporalAccessor parse(String text, Locale locale) throws ParseException
if (this.source != null) {
throw new DateTimeParseException(
String.format("Unable to parse date time value \"%s\" using configuration from %s", text, this.source),
text, ex.getErrorIndex());
text, ex.getErrorIndex(), ex);
}
// else rethrow original exception
throw ex;
Expand Down
Expand Up @@ -16,6 +16,7 @@

package org.springframework.format.datetime.standard;

import java.time.DateTimeException;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
Expand Down Expand Up @@ -320,6 +321,35 @@ void testBindISODate() {
assertThat(binder.getBindingResult().getFieldValue("isoLocalDate")).isEqualTo("2009-10-31");
}

@Test
void isoLocalDateWithInvalidFormat() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
String propertyName = "isoLocalDate";
propertyValues.add(propertyName, "2009-31-10");
binder.bind(propertyValues);
BindingResult bindingResult = binder.getBindingResult();
assertThat(bindingResult.getErrorCount()).isEqualTo(1);
FieldError fieldError = bindingResult.getFieldError(propertyName);
assertThat(fieldError.unwrap(TypeMismatchException.class))
.hasMessageContaining("for property 'isoLocalDate'")
.hasCauseInstanceOf(ConversionFailedException.class).getCause()
.hasMessageContaining("for value '2009-31-10'")
.hasCauseInstanceOf(IllegalArgumentException.class).getCause()
.hasMessageContaining("Parse attempt failed for value [2009-31-10]")
.hasCauseInstanceOf(DateTimeParseException.class).getCause()
// Unable to parse date time value "2009-31-10" using configuration from
// @org.springframework.format.annotation.DateTimeFormat(pattern=, style=SS, iso=DATE, fallbackPatterns=[])
.hasMessageContainingAll(
"Unable to parse date time value \"2009-31-10\" using configuration from",
"@org.springframework.format.annotation.DateTimeFormat",
"iso=DATE", "fallbackPatterns=[]")
.hasCauseInstanceOf(DateTimeParseException.class).getCause()
.hasMessageStartingWith("Text '2009-31-10'")
.hasCauseInstanceOf(DateTimeException.class).getCause()
.hasMessageContaining("Invalid value for MonthOfYear (valid values 1 - 12): 31")
.hasNoCause();
}

@Test
void testBindISOTime() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
Expand Down Expand Up @@ -519,9 +549,12 @@ void patternLocalDateWithUnsupportedPattern() {
.hasMessageContainingAll(
"Unable to parse date time value \"210302\" using configuration from",
"@org.springframework.format.annotation.DateTimeFormat",
"yyyy-MM-dd", "M/d/yy", "yyyyMMdd", "yyyy.MM.dd");
"yyyy-MM-dd", "M/d/yy", "yyyyMMdd", "yyyy.MM.dd")
.hasCauseInstanceOf(DateTimeParseException.class).getCause()
.hasMessageStartingWith("Text '210302'")
.hasNoCause();
}
}
}


public static class DateTimeBean {
Expand Down

0 comments on commit d168748

Please sign in to comment.