0

I have seen How to use LocalDateTime RequestParam in Spring? I get "Failed to convert String to LocalDateTime" but I am still having problems.

So writing a Spring Boot app which has a rest api.

The controller is

@RequestMapping(value = "/api/v1/climates/locationdates/{location}/{sdate}/{edate}", method = RequestMethod.GET)
   public ResponseEntity<Object> getClimate(@PathVariable("location") long location,
                                             @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") LocalDateTime sdate, 
                                             @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime edate) {
      System.out.println("CONTROLLER location is " + location + " start is " + sdate + " end is " + edate);           
      return new ResponseEntity<>(climateService.getClimatesByLocationAndDates(location, sdate, edate), HttpStatus.OK);
   }

When I use curl (using the same date format as I use for creating records)

curl -k -w "\n" -H "Authorization: Bearer $TOKEN" https://mint191:8453/api/v1/climates/locationdates/1/2019-12-17T11:30:00/2019-12-17T11:55:00

I get a response of

{"timestamp":"2019-12-19T11:05:21.707+0000","status":500,"error":"Internal Server Error","message":"Value must not be null!; nested exception is java.lang.IllegalArgumentException: Value must not be null!","path":"/api/v1/climates/locationdates/1/2019-12-17T11:30:00/2019-12-17T11:55:00"}

And in the log

CONTROLLER location is 1 start is null end is null

Request and Response is completed

2019-12-19 11:05:21.668 ERROR 21113 --- [nio-8453-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: Value must not be null!; nested exception is java.lang.IllegalArgumentException: Value must not be null!] with root cause

java.lang.IllegalArgumentException: Value must not be null! at org.springframework.util.Assert.notNull(Assert.java:198) ~[spring-core-5.2.2.RELEASE.jar!/:5.2.2.RELEASE]

The model is

@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "climate_gen")
private long id;

private float temperature;
private float humidity;
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss")
private LocalDateTime date;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "location_id", nullable = false)
private Location location;

So the date string 2019-12-17T11:55:00 is not being converted to a LocalDatTime object. What am I doing wrong?

PS. Have used different patterns just to see if one worked.

John
  • 1,593
  • 3
  • 17
  • 28

3 Answers3

0

I would suggest several workarounds.

  1. Don't just pass LocalDateTime Variable but wrap it in some class (along with other params) and in your wrapper class annotate it as:

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")

  2. Pass it as String and parse it using DateTimeFormatter on the server-side

Michael Gantman
  • 7,315
  • 2
  • 19
  • 36
0

Missing is:

@PathVariable("sdate")
@PathVariable("edate")

hence they stay null. ;)

Tip: if it does not work, start with a simplified prototype; ideally a unit test. Then one can consecutively add/remove an element, like the formatter annotation, using LocalDateTime and such.

Also the ISO format seems to be the standard format (not sure about ms), and ZonedDateTime might be more user friendly.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
0

Add @PathVariable to both sdate and edate to access value from url like this:

@RequestMapping(value = "/api/v1/climates/locationdates/{location}/{sdate}/{edate}", method = RequestMethod.GET)
    public ResponseEntity<Object> getClimate(@PathVariable("location") long location,
            @PathVariable("sdate") @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") LocalDateTime sdate,
            @PathVariable("edate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime edate) {

         System.out.println("CONTROLLER location is " + location + " start is " + sdate + " end is " + edate);           
         return new ResponseEntity<>(climateService.getClimatesByLocationAndDates(location, sdate, edate), HttpStatus.OK);
   }
Nitika Bansal
  • 740
  • 5
  • 10
  • I obviously misunderstood the stackoverflow entry I referenced. Many thanks @Nitika. – John Dec 20 '19 at 08:51