Skip to content

Improve default experience of data binding from HTML date and time input fields #24370

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
odrotbohm opened this issue Jan 15, 2020 · 1 comment
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: documentation A documentation task
Milestone

Comments

@odrotbohm
Copy link
Member

tl;dr

The default Spring MVC date/time form binding is slightly at odds with the way modern date and time form input fields are submitted by browsers. This results in the need for (quite a bit of) explicit binding configuration to make default form submissions from browsers work.

Details

The current Spring MVC way of binding of date value stems from the time when date and time values were handled through simple <input type="text" … /> elements. When working with those, form values were usually rendered in the format that's matching the user's browser's locale. On form submissions Spring MVC would then consider the Locale provided (usually in an HTTP header sent by the browser or a value otherwise obtained from the request) when parsing the value provided.

The form elements of type date and time have been specified to contain values that roughly match the ISO formats for dates and times. That means that when using those explicit types, the browser now sends an ISO format but still a browser specific locale. Depending on the actual locale, this might cause the binding to fail, depending on whether the format backing the locale is compatible with the ISO format.

Assume a form backing object like this

class Form {
  LocalDate date;
  LocalTime time;
}

E.g. a browser submission with German locale with a date of 2019-01-15 and time of 20:15 would fail for the date binding, as the German flavor is 15.01.2019 but binding the time would
succeed as by accident the German format parses ISO times properly.

Solutions / Workarounds

Annotating the form backing object

A very obvious way of fixing this is annotating all relevant form object fields with @DateTimeFormat(iso = …). While this works, it's a bit tedious one you have many of these types. Also, it's a bit surprising that the default configuration is not able to bind the standard values produced by the browser in the first place. On the other hand, Spring MVC cannot actually know whether the value it's supposed to bind is coming from a text field or a date specific one, especially considering the large amounts of existing applications.

Define ISO formats to be used for all date types globally

Using Spring MVC's WebMvcConfigurer one can tweak the form binding to globally use ISO formats like this:

@Bean
WebMvcConfigurer isoDatesByDefault() {
  return new WebMvcConfigurer() {
    public void addFormatters(FormatterRegistry registry) {
      DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
      registrar.setUseIsoFormat(true);
      registrar.registerFormatters(registry);
    }
  }
}

This has the advantage of avoiding the need for additional annotations on form backing objects. It of course breaks the date submission in any other formats (e.g. from plain text input fields using a format other than ISO).

Questions / Remarks

The Spring reference documentation seems a bit dated as it discusses the form binding of dates from the legacy Date point of view. Also, declaring a custom FormattingConversionService is not really idiomatic in a Spring Boot context in which you'd rather declare a WebMvcConfigurer to tweak the service.

I was wondering whether it might makes sense to let Boot expose a property to enable the configuration tweaks shown above to simplify switching to the ISO format in general. There's precedence in ISO date specific configuration in the Jackson space.

@odrotbohm odrotbohm added the in: web Issues in web modules (web, webmvc, webflux, websocket) label Jan 15, 2020
@rstoyanchev rstoyanchev self-assigned this Jan 15, 2020
@rstoyanchev rstoyanchev added the type: documentation A documentation task label Jan 15, 2020
@rstoyanchev rstoyanchev added this to the 5.2.4 milestone Jan 15, 2020
@rstoyanchev
Copy link
Contributor

I've scheduled this for a documentation update at least. If anything more comes of the investigation, we'll create separate tickets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: documentation A documentation task
Projects
None yet
Development

No branches or pull requests

2 participants