Reputation: 1817
I have Get request
localhost:8080/company/{id}/resource?fromDate=2020-12-03T18:01:00Z&toDate=2020-12-03T18:12:00Z
In this request fromDate and toDate are optional, so basically I can call
localhost:8080/company/{id}/resource
And it will return response for me.
Now I want to validate in correct way that both fromDate and toDate were passed or neither of thme were passed.
@GetMapping(value = "/company/{id}/resource")
public String getParameterOverride(
@PathVariable String id,
@RequestParam(required = false) @DateTimeFormat(iso = ISO.DATE_TIME) ZonedDateTime fromDate,
@RequestParam(required = false) @DateTimeFormat(iso = ISO.DATE_TIME) ZonedDateTime toDate
) {
// check dates logic
return id;
}
The problem is that I don't want to write something like
if(fromDate == null && toDate == null) {
...
}
I'm using Spring Boot. Is there any other way to validate this fields? My idea was to create new POJO and then validate them there, but I didn't manage to figure out how to do it. How to check that both fileds are present in POJO or vise versa? And also From Date is before to Date?
Upvotes: 0
Views: 873
Reputation: 1817
Ok, I found solution which I was seeking for.
Just to check this two parameters in if statement was very straightforward approach which I believe is not reusable.
I found out that you can map you request params fields by name directly into POJO. Then using validation you can create constraint which will check two dependent fields for any condition you like.
Lets say you have request
http://localhost:8080/myresource?dateFrom=2020-01-01&dateTo=2020-01-02
Then you controller:
@GetMapping(value = "/myresource")
public String getMyResource(@Valid DateRangePojo dateRangePojo ) {
return null;
}
My question was "how to validate that you have both dateFrom and dateTo or neither of them".
Then Pojo
@Data
@CheckDateRange
public class DateRangePojo {
@DateTimeFormat(iso = ISO.DATE_TIME)
private final ZonedDateTime dateFrom;
@DateTimeFormat(iso = ISO.DATE_TIME)
private final ZonedDateTime dateTo;
}
@CheckDateRange- is custom annotation to check if present both dates.
@Target({ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CheckDatesValidator.class)
public @interface CheckDateRange{
String message() default "";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class CheckDatesValidator implements ConstraintValidator<CheckDateRange, DateRangePojo> {
@Override
public boolean isValid(final DateRangePojo value, final ConstraintValidatorContext context) {
// your logic to check if valid
}
}
Every time when new request comes it will be validate by isValid method.
Upvotes: 1
Reputation: 40058
You can declare them with Optional
if the request param is optional
@RequestParam(required = false) @DateTimeFormat(iso = ISO.DATE_TIME) Optional<ZonedDateTime> fromDate,
@RequestParam(required = false) @DateTimeFormat(iso = ISO.DATE_TIME) Optional<ZonedDateTime> toDate
And then in code you don't need multiple checks, Optional.map
will only get executed if Optional
is not empty
if(fromDate.isPresent() && toDate.isPresent()) {
return //value
}
fromDate.map(/*call method*/).orElseGet(()-> toDate.map(/*call method*/).orElse(/*default value*/));
Upvotes: 0
Reputation: 335
Use @Valid
annotation to check if the datatype is valid like very basic one
@GetMapping(value = "/company/{id}/resource")
public String getParameterOverride(
@PathVariable String id,
@RequestParam(required = false) @DateTimeFormat(iso = ISO.DATE_TIME) @Valid ZonedDateTime fromDate,
@RequestParam(required = false) @DateTimeFormat(iso = ISO.DATE_TIME) @Valid ZonedDateTime toDate
) {
// check dates logic
return id;
}
For a more customized one, you can look for ConstraintValidator
Upvotes: 0