Let’s say we want to task the back-end REST API application with validating the syntax of an email address provided by a new user while doing the registration. Aside from the fact that the “first level” validation should always happen on the front-end side (using for example a JavaScript solution) it is still a good idea to do a “second level” validation on the back-end (a user can have JavaScript support disabled in his/her browser or try some dirty hacks on our webpage and be sending invalid data to the server causing inconsistencies at best).
What would be a nice approach to handle server-side validation? A custom annotation – something like @ValidEmailSyntax
Here’s an idea on how to implement it:
1) Create an interface for the Validation Annotation:
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EmailSyntaxValidator.class)
@Documented
public @interface ValidEmailSyntax {
String message() default "Invalid email syntax";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
- As you can see from the code above, our @ValidEmailSyntax annotation can be used to annotate a field, method or another annotation
- “Invalid email syntax” is the message returned by the server in case of failed validation
2) Create a EmailSyntaxValidator class that will be responsible for making decision whether the subject of validation (field, method, etc…) is valid or not:
@Component
public class EmailSyntaxValidator implements ConstraintValidator<ValidEmailSyntax, EmailAddressType> {
protected final Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void initialize(ValidEmailSyntax constraintAnnotation) {
logger.debug("EmailSyntaxValidator initialization successful");
}
@Override
public boolean isValid(EmailAddressType value, ConstraintValidatorContext context) {
return value == null || Pattern.compile(EmailStructure.PATTERN, Pattern.CASE_INSENSITIVE).matcher(value.getEmail()).matches();
}
}
3) The validator class above will validate the the email represented by following EmailAddressType object:
@JsonSerialize(using = ToStringSerializer.class)
public class EmailAddressType implements Serializable {
private static final long serialVersionUID = 1L;
private String email;
public EmailAddressType(String email) {
this.email = email;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return email;
}
}
4) …against the following email structure pattern (represented by an EmailStructure interface):
public interface EmailStructure {
static final String ATOM = "[a-z0-9!#$%&'*+/=?^_`{|}~-]";
static final String DOMAIN = "(" + ATOM + "+(\\." + ATOM + "+)+";
static final String IP_DOMAIN = "\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\]";
static final String PATTERN = "^" + ATOM + "+(\\." + ATOM + "+)*@" + DOMAIN + "|" + IP_DOMAIN + ")$";
}
5) finally this is how we will use the validation annotation in our code:
public class User {
@ValidEmailSyntax
private EmailAddressType email;
...
//getters and setters ommited
}
Happy coding! 🙂
Tagged: API, Java, REST, Validation


Leave a comment