spring-cloud-openfeign
spring-cloud-openfeign copied to clipboard
Feign client doesn't serialize java.time.LocalDate's correctly while it present as object field
I'm using Spring boot 2.4.5, Spring Cloud 2020.0.3, Java 11.
Is there a way to use a Feign client accepting a java.time.LocalDate
as an object field where it is supposed to comply with a given format like @DateTimeFormat
with some specific pattern?
For instance, I have the next object which I wanna represent as query params:
@AllArgsConstructor
public class QueryRequestParams {
@DateTimeFormat(pattern = "dd.MM.yyyy")
private LocalDate from;
@DateTimeFormat(pattern = "dd.MM.yyyy")
private LocalDate to;
}
The instance of QueryRequestParams looks like:
new QueryRequestParams(LocalDate.parse("2011-12-03"), LocalDate.parse("2011-12-05"))
The feign client is:
@FeignClient(url = "http://localhost:9000")
public interface ExampleFeignClient {
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
List<Object> getObjects(@SpringQueryMap QueryRequestParams queryRequestParams);
}
When feign client does request and
QueryRequestParams` object has no null values the request look like as "http://localhost:9000?from=2011-12-03&to=2011-12-05" which has another format rather than I configured via DateTimeFormat annotation.
When I tried to use @DateTimeFormat with @RequestParam annotation just in ExampleFeignClient, for example:
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
List<Object> getObjects(@RequestParam("from") @DateTimeFormat(pattern = "dd.MM.yyyy") LocalDate from,
@RequestParam("to") @DateTimeFormat(pattern = "dd.MM.yyyy") LocalDate to);
then it works as I expected.
It there a way to use @SpringQueryMap
with object which contains LocalDate
field and that is formatted via @DateTimeFormat(pattern = "dd.MM.yyyy")
annotation?
Thanks for any help!
Hi @DmitriiVashchenko,
I think your expectation works on newer version of feign. I'm using Spring boot 2.5.2, Spring Cloud 2020.0.3, Java 11.
@SpringBootApplication
@EnableFeignClients
@Slf4j
public class FeignCanApplication {
public static void main(String[] args) {
SpringApplication.run(FeignCanApplication.class, args);
}
@Autowired
private TestClient testClient;
@Bean
public ApplicationRunner test() {
return args -> {
List<LocalDate> dateList = testClient.getObjects(new QueryRequestParams(LocalDate.parse("2011-12-03"), LocalDate.parse("2011-12-05")));
log.info("{}", dateList);
};
}
@FeignClient(name = "test", url = "http://localhost:8080")
public interface TestClient {
@GetMapping(value = "/get-data", produces = MediaType.APPLICATION_JSON_VALUE)
List<LocalDate> getObjects(@SpringQueryMap QueryRequestParams queryRequestParams);
}
@RestController
@Slf4j
public static class TestController {
@GetMapping(value = "/get-data", produces = MediaType.APPLICATION_JSON_VALUE)
List<LocalDate> getObjects(@RequestParam("from") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate from,
@RequestParam("to") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate to) {
log.info("{} {}", from, to);
return Arrays.asList(from, to);
}
}
@AllArgsConstructor
@Data
public class QueryRequestParams {
@DateTimeFormat(pattern = "dd.MM.yyyy")
private LocalDate from;
@DateTimeFormat(pattern = "dd.MM.yyyy")
private LocalDate to;
}
}
Example output:
If I am wrong in somewhere, please share small code block so I can try to help more.
Hi @cbezmen, but your date formation is also different from the pattern. I expect the date to be shaped like dd.MM.yyy when this date field is represented as an object field and I using this like:
public class QueryRequestParams {
@DateTimeFormat(pattern = "dd.MM.yyyy")
private LocalDate from;
@DateTimeFormat(pattern = "dd.MM.yyyy")
private LocalDate to;
}
@FeignClient(name = "test", url = "http://localhost:8080")
public interface TestClient {
@GetMapping(value = "/get-data", produces = MediaType.APPLICATION_JSON_VALUE)
List<LocalDate> getObjects(@SpringQueryMap QueryRequestParams queryRequestParams);
}
Hi @DmitriiVashchenko
I think it is not spring-open-feign problem.
DateTimeFormat.ISO
only supports:
- DATE
- TIME
- DATE_TIME
- NONE
You can add custom conversion service. Please check this link https://www.baeldung.com/spring-date-parameters
@cbezmen, but this way works fine
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
List<Object> getObjects(@RequestParam("from") @DateTimeFormat(pattern = "dd.MM.yyyy") LocalDate from,
@RequestParam("to") @DateTimeFormat(pattern = "dd.MM.yyyy") LocalDate to);
Here also @DateTimeFormat annotation with LocalDate type, just presented as separate param, not field of object
Hi @DmitriiVashchenko,
QueryRequestParams is also fail with dd.MM.yyyy
because it is not a valid pattern. When you call it with wrong pattern it will throw DateTimeParseException. You have to send supported patterns of DateTimeFormat.ISO.
public class QueryRequestParams {
@DateTimeFormat(pattern = "dd.MM.yyyy")
private LocalDate from;
@DateTimeFormat(pattern = "dd.MM.yyyy")
private LocalDate to;
}
new QueryRequestParams(LocalDate.parse("13-12-2011"), LocalDate.parse("12-05-2011")) // this will throw DateTimeParseException
@DmitriiVashchenko, @cbezmen is right - this will, in fact, throw an exception.
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.
I have the same problem with ZonedDateTime I have a parameter
@DateTimeFormat(pattern = "yyyyMMdd'T'HHmmss'Z'")
private ZonedDateTime scheduledFrom;
When I declare the param as direct method param
@GetMapping(value = "/example")
Map<String, Object> example(@RequestParam @DateTimeFormat(pattern = "yyyyMMdd'T'HHmmss'Z'") ZonedDateTime scheduledFrom);
the formatting works OK:
scheduledFrom=20220104T070640Z
However when I try using this param as a part of nested object among with @SpringQueryMap annotation
public class WrappedScheduledFrom {
@DateTimeFormat(pattern = "yyyyMMdd'T'HHmmss'Z'")
private ZonedDateTime scheduledFrom;
}
@GetMapping(value = "/example")
Map<String, Object> example(@SpringQueryMap WrappedScheduledFrom requestDto);
The formatting stops working:
scheduledFrom=2022-01-04T07:06:40Z[UTC]
I don't understand why has this issue been closed. What kind of feedback was expected to be provided?
From my side, I can confirm that @DateTimeFormat(pattern = "..."
on @SpringQueryMap
-annotated parameter is ignored by the client and resulting request consists of default ISO date format, as if @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
was given.
Will take a look at it.
I can also confirm, that feign send date as string with quotes "2022-05-25" when I use LocalDate in body's object with MediaType.MULTIPART_FORM_DATA_VALUE, for example:
@FeignClient(name = "api-client", url = "${base-url}/api", configuration = ApiConfig.class)
public interface EdoApiClient {
@PostMapping(value = "/documents/draft", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
DocumentResponse createDraft(DocumentRequest request);
}
@Getter
@Setter
public class DocumentRequest {
private String name;
private MultipartFile documentFile;
private LocalDate documentDate;
private draft boolean;
}
public class ApiConfig {
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
from logs
--180feeb2f1b
Content-Disposition: form-data; name="documentDate"
Content-Type: text/plain; charset=UTF-8
"2022-05-26"
--180feeb2f1b
Content-Disposition: form-data; name="draft"
Content-Type: text/plain; charset=UTF-8
true
I think feign.form.multipart.SingleParameterWriter must be applicable for LocalDate, LocalDateTime classes too.
@FrischTag @k0mmsussert0d @velykov - sorry for not getting back to you earlier - we were concentrating on the AOT/ native, jakarta and observability portfolio-wide efforts towards the end of 2022. If you would like us to take a closer look at it, please provide a minimal, complete, verifiable example that reproduces the issue as a link to a repo to a small executable app or tests that reproduce the issue rather than separate code snippets.
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.