Skip to content

devon4j validations

Helmke edited this page Oct 2, 2019 · 14 revisions

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 the values by adding annotations in our Java classes.

My Thai Star validations

In My Thai Star app we can find validations for some fields that we receive from the client.

The main part of the inputs from the client 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, for dates, checks that the 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 accounts. In this case the standard validator is not checking the domain of the email, so for My Thai Star we added a custom validator called '@EmailExtended' that is defined in a new 'general/common/api/validation/EmailExtended.java` class. In the next section we will see it in more detail.

Add your validations

In Jump the Queue app we have 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 trying to save to data base.

When registering a visitor the client provides:

  • 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.

  • accepterTerms: must be not null.

  • userType: must be not null.

Name validation

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 'visitormanagement/dataaccess/api/VisitorEntity.java' just before the field name

@NotNull
private String name;

Run the app with Eclipse and, using Postman or a similar tool, call the register resource (POST) http://localhost:8081/jumpthequeue/services/rest/visitormanagement/v1/visitor providing in the body a visitor object without a name

{
	"username": "[email protected]",
	"phoneNumber": "1234567",
	"password": "12345",
	"acceptedCommercial": "true",
	"acceptedTerms": "true",
	"userType": "false"
}

You will get a ValidationError message regarding the name field

jumpthequeue validation name

Email validation

In the case of the email, as we have already commented for My Thai Star, using the @Email annotation for validations will allow to enter emails like something@something. This does not fit the app requirements, so we need to add a custom email validator.

Add an annotation 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 that the fields annotated with @EmailExtended must match.

Now we can annotate the username field in with @NotNull and @EmailExtended to fit the app requirements.

@NotNull
@EmailExtended
private String username;

Then, if we try to register a user with a null email we get the ValidationError with message "{email=[may not be null]}"

jumpthequeue validation nullemail

And if we provide an email that does not match the expected format we get the related ValidationError

jumpthequeue validation wrongemail

Finally if we provide a valid email the registration process ends successfully.

Phone validation

For validating the phone, apart from the @NotNull annotation, we need to use again a custom validation based on the @Pattern annotation and a regular expression.

We are going to follow the same approach used for EmailExtended validation.

Add an annotation Phone.java to the general.common.api.validation package. With the @Pattern annotation we can define a regular expression to filter phones ("consists of sequence of numbers or spaces").

Phone.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.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 last step we can test our new validation. Call again the service defining a wrong phone, the response should be a ValidationError like the following

jumpthequeue validation wrongphone

However, if we provide a valid phone the process should end successfully

In this chapter we have seen how easy is to add validations in the server side of our devon4j applications. In the next chapter we will show how to test our components using Spring Test and devon4j's test module.


Next chapter: Testing in devon4j