How to extend Bean Validation: thermometer_face:
Mostly a copy of the code in Constraint composition: sweat:
AllowSingleInput.java
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
@Documented
@Constraint(validatedBy = {AllowSingleInputValidator.class}) //Class made with ↓
@Target({TYPE, ANNOTATION_TYPE}) //Allow it to be attached only to classes or annotations
@Retention(RUNTIME)
public @interface AllowSingleInput {
String message() default "{com.neriudon.example.validator.SingleInput.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String[] fields(); //Make an array
@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Documented
@interface List {
AllowSingleInput[] value();
}
}
The point is to target the annotation only to the class or annotation, and to have an array of String
in the field.
You can write the message solidly, but I have set Please input to only one text filed
in the properties.
Now, let's create a class that does the actual input check. Well, the basics are a copy of Example: sweat:
AllowSingleInputValidator.java
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.util.StringUtils;
public class AllowSingleInputValidator implements ConstraintValidator<AllowSingleInput, Object> {
private String[] fields;
private String message;
@Override
public void initialize(AllowSingleInput constraintAnnotation) {
fields = constraintAnnotation.fields(); //Get field name
message = constraintAnnotation.message();
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
BeanWrapper beanWrapper = new BeanWrapperImpl(value);
//Process to check if any one field is entered
boolean isSingleInput = false;
for (String field : fields) {
if (!StringUtils.isEmpty(beanWrapper.getPropertyValue(field))) {
if (isSingleInput) {
isSingleInput = false;
break;
} else {
isSingleInput = true;
}
}
}
if (isSingleInput) {
return true;
} else {
context.disableDefaultConstraintViolation();
//Message output if conditions are not met
context.buildConstraintViolationWithTemplate(message).addPropertyNode(fields[0])
.addConstraintViolation();
return false;
}
}
}
I get the target field name with ʻinitialize and check if it is entered in only one of the fields with ʻisValid
(maybe there is another good way to write it: frowning2 :).
Annotate the Form
class and set the field name to check the input in fields
.
@AllowSingleInput(fields = {"todoTitle1", "todoTitle2", "todoTitle3"})
public class TodoForm implements Serializable {
private static final long serialVersionUID = 1L;
private String todoTitle1;
private String todoTitle2;
private String todoTitle3;
// getter/omit setter
}
There is no need to change jsp.
<!--Extract only the Form-->
<form:form action="${pageContext.request.contextPath}/todo/create"
method="post" modelAttribute="todoForm">
<form:label path="todoTitle1"/>
<form:input path="todoTitle1" />
<form:errors path="todoTitle1" cssClass="text-error" /><br>
<form:label path="todoTitle2"/>
<form:input path="todoTitle2" />
<form:errors path="todoTitle2" cssClass="text-error" /><br>
<form:label path="todoTitle3"/>
<form:input path="todoTitle3" />
<form:errors path="todoTitle3" cssClass="text-error" /><br>
<form:button>Create Todo</form:button>
</form:form>
You can now get an error message when you fill in multiple fields and press a button: v :.
As a memo because I needed this validator for the project I was involved in.
Recommended Posts