I use Spring Boot and included jackson-datatype-jsr310
with Maven:
com.fasterxml.jackson.datatype
You did everything correct :) . Here is an example that shows exactly what you are doing. Just Annotate your RequestParam with @DateTimeFormat
. There is no need for special GenericConversionService
or manual conversion in the controller. This blog post writes about it.
@RestController
@RequestMapping("/api/datetime/")
final class DateTimeController {
@RequestMapping(value = "datetime", method = RequestMethod.POST)
public void processDateTime(@RequestParam("datetime")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime dateAndTime) {
//Do stuff
}
}
I guess you had an issue with the format. On my setup everything works well.
I ran into the same problem and found my solution here (without using Annotations)
...you must at least properly register a string to [LocalDateTime] Converter in your context, so that Spring can use it to automatically do this for you every time you give a String as input and expect a [LocalDateTime]. (A big number of converters are already implemented by Spring and contained in the core.convert.support package, but none involves a [LocalDateTime] conversion)
So in your case you would do this:
public class StringToLocalDateTimeConverter implements Converter<String, LocalDateTime> {
public LocalDateTime convert(String source) {
DateTimeFormatter formatter = DateTimeFormatter.BASIC_ISO_DATE;
return LocalDateTime.parse(source, formatter);
}
}
and then just register your bean:
<bean class="com.mycompany.mypackage.StringToLocalDateTimeConverter"/>
With Annotations
add it to your ConversionService:
@Component
public class SomeAmazingConversionService extends GenericConversionService {
public SomeAmazingConversionService() {
addConverter(new StringToLocalDateTimeConverter());
}
}
and finally you would then @Autowire in your ConversionService:
@Autowired
private SomeAmazingConversionService someAmazingConversionService;
You can read more about conversions with spring (and formatting) on this site. Be forewarned it has a ton of ads, but I definitely found it to be a useful site and a good intro to the topic.
TL;DR - you can capture it as a string with just @RequestParam
, or you can have Spring additionally parse the string into a java date / time class via @DateTimeFormat
on the parameter as well.
the @RequestParam
is enough to grab the date you supply after the = sign, however, it comes into the method as a String
. That is why it is throwing the cast exception.
There are a few ways to achieve this:
@GetMapping("/test")
public Page<User> get(@RequestParam(value="start", required = false) String start){
//Create a DateTimeFormatter with your required format:
DateTimeFormatter dateTimeFormat =
new DateTimeFormatter(DateTimeFormatter.BASIC_ISO_DATE);
//Next parse the date from the @RequestParam, specifying the TO type as
a TemporalQuery:
LocalDateTime date = dateTimeFormat.parse(start, LocalDateTime::from);
//Do the rest of your code...
}
@GetMapping("/test")
public void processDateTime(@RequestParam("start")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
LocalDateTime date) {
// The rest of your code (Spring already parsed the date).
}
If you use the dependency spring-boot-starter-web version 2.0.0.RELEASE
or higher, there is no longer needed to explicitely include jackson-datatype-jsr310
dependency, which is already provided with spring-boot-starter-web
through spring-boot-starter-json.
This was resolved as Spring Boot issue #9297 and the answer is still valid and relevant:
@RequestMapping(value = "datetime", method = RequestMethod.POST)
public void foo(@RequestParam("dateTime")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime ldt) {
// IMPLEMENTATION
}
For global configuration :
public class LocalDateTimePropertyEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
setValue(LocalDateTime.parse(text, DateTimeFormatter.ISO_LOCAL_DATE_TIME));
}
}
And then
@ControllerAdvice
public class InitBinderHandler {
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(OffsetDateTime.class, new OffsetDateTimePropertyEditor());
}
}
I found workaround here.
Spring/Spring Boot only supports the date/date-time format in BODY parameters.
The following configuration class adds support for date/date-time in QUERY STRING (request parameters):
// Since Spring Framwork 5.0 & Java 8+
@Configuration
public class DateTimeFormatConfiguration implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
registrar.setUseIsoFormat(true);
registrar.registerFormatters(registry);
}
}
respectively:
// Until Spring Framwork 4.+
@Configuration
public class DateTimeFormatConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addFormatters(FormatterRegistry registry) {
DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
registrar.setUseIsoFormat(true);
registrar.registerFormatters(registry);
}
}
It works even if you bind multiple request parameters to some class (@DateTimeFormat
annotation helpless in this case):
public class ReportRequest {
private LocalDate from;
private LocalDate to;
public LocalDate getFrom() {
return from;
}
public void setFrom(LocalDate from) {
this.from = from;
}
public LocalDate getTo() {
return to;
}
public void setTo(LocalDate to) {
this.to = to;
}
}
// ...
@GetMapping("/api/report")
public void getReport(ReportRequest request) {
// ...