User Registration Validation in Spring

NixMash Spring v0.1.6 adds Spring Security and a new registration form with validation. Below is the registration form displaying both global errors and individual property errors.

We're using a UserDTO object and Hibernate validation for individual field issues like the First Name field above.

@NotEmpty
@Length(min=User.MIN_LENGTH_FIRST_NAME, max=User.MAX_LENGTH_FIRST_NAME)
private String firstname = "";

To display the message we include the Hibernate property layout in our messages.properties file.

Length.userDTO.firstname=First name must be between {2} and {1} characters

We're using a custom EmailValidator to enforce full domain email syntax.

@Pattern(regexp=".+@.+\\..+", message="{ExtendedEmailValidator.email}")
@Target( { METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = {})
@Documented
public @interface ExtendedEmailValidator {
    String message() default "{ExtendedEmailValidator.email}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

UserCreateFormValidator

Perhaps the most interesting aspect of New User Validation is our UserCreateFormValidator class for catching issues like a pre-existing usernames or passwords not matching. The custom validator extends org.springframework.validation.Validator and is initialized in the Registration Controller.

@InitBinder("userDTO")
public void initBinder(WebDataBinder binder) {
binder.addValidators(userCreateFormValidator);
}

An @Override validate() method in UserCreateFormValidator makes it easy to test multiple scenarios, like testing for the existence of the username.

private void validateUsername(Errors errors, UserDTO form) {
if (userService.getUserByUsername(form.getUsername()) != null) {
errors.reject("user.exists", "User with this username already exists");
}
}

Thymeleaf

No post on form validation would be complete without a quick look at Thymeleaf on the client side.

The form includes a GlobalErrors area to catch multiple errors caught by the UserCreateFormValidator.

<div th:if="${#fields.hasGlobalErrors()}"
class="has-error col-lg-offset-3 alert alert-dismissible alert-danger">
	<button type="button" class="close" data-dismiss="alert">×</button>
	<label class="control-label" th:each="err : ${#fields.globalErrors()}" th:text="${err}">...</label>
</div>

Each field includes a small bit of code to catch the possibility of a field error, including a label and the ability to change the field display.

<div class="form-group" th:classappend="${#fields.hasErrors('firstname')} ? 'has-error'">
	<label for="firstname" class="col-lg-3 control-label" th:text="#{register.form.firstname}">[First
	    Name]</label>

	<div class="col-lg-9">
	    <input type="text" th:field="*{firstname}" class="form-control"/>
	    <label class="control-label" th:errors="*{firstname}">[error]</label>
	</div>
</div>

All source code described in this post is available in NixMash Spring v0.1.6 on GitHub.

Posted August 17, 2015 11:59 AM EDT

More Like This Post