Bohdan Myslyvchuk
Bohdan Myslyvchuk

Reputation: 1817

How to validate that fromDate and toDate both exist or absent in get request with Spring Boot

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

Answers (3)

Bohdan Myslyvchuk
Bohdan Myslyvchuk

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

Ryuzaki L
Ryuzaki L

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

Himadri Mandal
Himadri Mandal

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

Related Questions