Validate at least one of three field in dto spring boot

Viewed 2608

I have a DTO that looks something like this:

class VehicleDto {
    private String type;
    private Car car;
    private Bike bike;
}

Now depending on the type, I need to validate on at least one of Car and Bike.

Both cannot be present in the same request.

How can I do that?

2 Answers

For example, if we want to check whether my TaskDTO object is valid, by comparing its two attributes dueDate and repeatUntil , following are the steps to achieve it.

dependency in pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

DTO class:

@ValidTaskDTO
public class TaskDTO {

    @FutureOrPresent
    private ZonedDateTime dueDate;

    @NotBlank(message = "Title cannot be null or blank")
    private String title;

    private String description;

    @NotNull
    private RecurrenceType recurrenceType;

    @Future
    private ZonedDateTime repeatUntil;

}

Custom Annotation:

@Constraint(validatedBy = {TaskDTOValidator.class})
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidTaskDTO {
    String message() default "Due date should not be greater than or equal to Repeat Until Date.";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

Constraint Validator:

public class TaskDTOValidator implements ConstraintValidator<ValidTaskDTO, TaskDTO> {
    @Override
    public void initialize(ValidTaskDTO constraintAnnotation) {

    }

    @Override
    public boolean isValid(TaskDTO taskDTO, ConstraintValidatorContext constraintValidatorContext) {
        if (taskDTO.getRecurrenceType() == RecurrenceType.NONE) {
            return true;
        }

        return taskDTO.getRepeatUntil() != null && taskDTO.getDueDate().isBefore(taskDTO.getRepeatUntil());
    }
}

Make sure that you have @Valid in front of RequestBody of a postmapping method in your RestController. Only then the validation will get invoked:

@PostMapping
public TaskReadDTO createTask(@Valid @RequestBody TaskDTO taskDTO) {
.....
}

I hope this helps. If you need a detailed explanation on steps, have a look at this video

Related