-
Notifications
You must be signed in to change notification settings - Fork 45
devon4j validations
For validations, devon4j includes the Hibernate Validator as one of the available libraries in the pom.xml file.
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
Hibernate Validator allow us to check received values, by adding annotations to our Java classes.
In the MyThaiStar app, we can find validations for some fields that we receive from the client.
The main part of client inputs is related to the booking process. The client needs to provide: name
, comment
, bookingDate
, email
and assistants
.
@NotNull
private String name;
...
private String comment;
@NotNull
@Future
private Timestamp bookingDate;
...
@NotNull
@EmailExtended
private String email;
...
@Min(value = 1, message = "Assistants must be greater than 0")
@Digits(integer = 2, fraction = 0)
private Integer assistants;
-
@NotNull
: Checks that the field is not null before saving in the database. -
@Future
: Checks that a provided date is not in the past. -
@Min
: Declares a minimum value for an integer. -
@Digits
: Checks the format of an integer. -
@Email
: Is the standard validator for email addresses. In this case the standard validator is not checking the domain of the email, so for MyThaiStar we added a custom validator called@EmailExtended
that is defined in a newgeneral/common/api/validation/EmailExtended.java
class. We will see it in more detail in the next section.
In the JumpTheQueue app, we receive some inputs from the client. So let’s add some validations for that data, to avoid errors and ensure the consistency of the information, before saving it to the database.
When registering a visitor, the client provides the following information:
-
username
: Must be not null and must match the format<name>@<domain.toplevel>
. -
name
: Must be not null. -
phoneNumber
: Must be not null and must match a sequence of numbers and spaces. -
password
: Must be not null. -
acceptedCommercial
: Must be not null. -
acceptedTerms
: Must be not null. -
userType
: Must be not null.
As we have just mentioned, the name of the visitor must be not null. To do so, Hibernate Validator provides us with the already mentioned @NotNull
annotation (javax.validation.constraints.NotNull
).
We are going to add the annotation in the jtqj-core
to visitormanagement/dataaccess/api/VisitorEntity.java
, just before the field name:
...
@NotNull
private String name;
...
Run the app with Eclipse and — using Postman — call the register resource via POST:
http://localhost:8081/jumpthequeue/services/rest/visitormanagement/v1/visitor
In the body, provide a visitor object without a name, like so:
{
"username" : "mary@mail.com",
"phoneNumber" : "1234567",
"password" : "12345",
"acceptedCommercial" : "true",
"acceptedTerms" : "true",
"userType" : "false"
}
You will get a ValidationError message regarding the name field:
In the case of the email — as already explained in the MyThaiStar section — using the @Email
annotation for validation, will allow users to enter emails such as something@something
. This does not fit our app requirements, so we need to add a custom email validator.
In jtqj-core
, add a class for our annotation, called EmailExtended.java
, in a new general.common.api.validation
package:
EmailExtended.java
...
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.constraints.Email;
import javax.validation.constraints.Pattern;
@Email
@Pattern(regexp = ".+@.+\\..+", message = "Email must specify a domain")
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {})
@Documented
public @interface EmailExtended {
String message() default "Please provide a valid email address";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
This validator extends the @Email
validation with an extra @Pattern
, that defines a regular expression, which the fields annotated with @EmailExtended
must match.
Now we can annotate the username field in our VisitorEntity.java
with @NotNull
and @EmailExtended
, to fit the app requirements.
...
@NotNull
@EmailExtended
private String username;
...
Then, if we restart the app and try to register a user without an email, we get a ValidationError with the message: "{username=[must not be null]}":
And if we provide an email, that does not match the expected format, we get the related ValidationError with the message: "{username=[Email must specify a domain, …]}":
Finally, if we provide a valid email, the registration process ends successfully.
For validating the phone, apart from the @NotNull
annotation, we need to use another custom validation, based on the @Pattern
annotation and a regular expression.
We are going to follow the same approach used for the EmailExtended
validation.
In jtqj-core
, add a class for our annotation, called Phone.java
to the general.common.api.validation
package. With the @Pattern
annotation we can define a regular expression to filter for phone numbers ("consists of sequence of numbers or spaces"):
...
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.constraints.Pattern;
@Pattern(regexp = "[ 0-9]{0,14}$", message = "Phone must be valid")
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {})
@Documented
public @interface Phone {
String message() default "Phone must be well formed";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Then we only need to apply the new validation to our phone field in visitormanagement/dataaccess/api/VisitorEntity.java
:
...
@NotNull
@Phone
private String phoneNumber;
...
As a last step, we can now test our new validation. Call the previous service again, defining a wrong phone number. The response should be a ValidationError
with the message: "{phoneNumber
=[Phone must be valid]}":
If we provide a valid phone number, the process should complete successfully.
In this chapter, we have seen how easy is to add validations to the server side of our devon4j applications. In the next chapter, we will show you how to test our components using Spring Test and devon4j's test module.
Next Chapter: Testing in devon4j
This documentation is licensed under the Creative Commons License (Attribution-NoDerivatives 4.0 International).