I'm currently studying building API's with Spring. I'm working with Spring Validator to validate my input. Here it is my custom validator:
public class NewHoldValidator implements Validator {
private EntityManager manager;
public NewHoldValidator(EntityManager manager) {
this.manager = manager;
}
@Override
public boolean supports(Class<?> clazz) {
return NewHoldRequest.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
if (errors.hasErrors()) {
return;
}
NewHoldRequest request = (NewHoldRequest) target;
Patron patron = manager.find(Patron.class, request.patronId);
BookInstance bookInstance = manager.find(BookInstance.class, request.bookInstanceId);
Assert.state(patron != null, "Patron does not exists.");
Assert.state(bookInstance != null, "Book instance does not exists.");
if (!bookInstance.acceptToBeHoldTo(patron)) {
errors.reject(null, "This book instance cannot be hold to this patron");
}
if (!request.hasDaysHold()) {
if (!patron.researcher()) {
errors.rejectValue("daysHold", null, "You need to pass a daysHold attribute");
}
}
}
}
And here is my NewHoldRequest class:
public class NewHoldRequest {
@NotNull
public final Long patronId;
@NotNull
public final Long bookInstanceId;
@Positive
@Max(60)
public final Integer daysHold;
public NewHoldRequest(@NotNull Long patronId, @NotNull Long bookInstanceId, @Positive @Max(60) Integer daysHold) {
this.patronId = patronId;
this.bookInstanceId = bookInstanceId;
this.daysHold = daysHold;
}
@Override
public String toString() {
return "NewHoldRequest{" + "patronId=" + patronId + ", bookId=" + bookInstanceId + ", daysHold=" + daysHold + '}';
}
public boolean hasDaysHold() {
return this.daysHold != null;
}
Even if my field "daysHold" is public I still need to create a getter to it so Spring can show the rejected error properly, otherwise, it will throw a NotReadablePropertyException. Is there a way to define that Spring can reject public fields without getters or I will need to add accessor methods to all fields I want to reject?
Here is the message that shows up when my validation is triggered.
org.springframework.beans.NotReadablePropertyException: Invalid property 'daysHold' of bean class [com.api.library.usecases.newhold.NewHoldRequest]: Bean property 'daysHold' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?