Enterprise Java

Java EE Bean Validation Example

1. Introduction

Hi Java Code Geeks fan! This article is about a Java EE Bean Validation Example. One coding practice that we should do is to always validate variables before using. In this example we validate the input received from the user to maintain data integrity. Maintaining data integrity is an important part of application logic. Validating data can take place at different layers. For example, the JavaServer Faces standard validators validate data at the presentation layer (e.g. validateLength, validateLongRange, etc.).

2. Bean Validation

JavaBeans Validation is part of the Java EE platform. It was made available starting with Java EE 6. The Bean Validation model is supported by constraints in the form of annotations placed on a field, method, or class of a JavaBeans component, such as a managed bean. There are many built-in constraints available in the javax.validation.constraints package. Furthermore, constraints can also be user defined or customized.

3. Bean Validation vs JSF Validation

To Bean validate or to JSF validate? That is the question. When should I use Bean validation? When should I use JSF validation? The short answer is it depends. It would depend on the requirement specification. But Bean validation has an advantage of being DRY. The validation logic is removed from the view and if configured at the entity level, it’s reusable for all frameworks other than JSF. If we use a bean multiple times, then we only write the validation once with Bean validation. In contrast, we would write JSF validation on every Facelets page which can lead to a maintenance headache.

4. Tools and Requirements

  1. Apache Maven
  2. Java 8
  3. WildFly 10.1.0
  4. Eclipse Oxygen
  5. Eclipse with WildFly and JBoss Tools Example

The source in this is example is based on the Java EE Web Project in Red Hat Central. We will not go through the details of setting up the project, so it is recommended that Eclipse with WildFly and JBoss Tools Example be read before trying out the example. We’ll be using WildFly 10.1.0 but later versions should work.

Once you have the tools and requirements done, import the java-ee-bean-validation-example project in Eclipse.

5. Backing Bean

Shown below is a fragment of IndexBacking.java. Open the said file in Eclipse to view the entire code.

IndexBacking.java

package com.javacodegeeks.example.backing;

import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
import javax.validation.constraints.Digits;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;

import com.javacodegeeks.example.constraints.CompanyEmail;

@Named
@RequestScoped
public class IndexBacking {

	@NotNull
    @Size(min = 1, max = 25)
    @Pattern(regexp = "[^0-9]*", message = "Must not contain numbers")
    private String name;

    @NotNull
    @NotEmpty
    @Email
    private String email;

    @NotNull
    @Size(min = 10, max = 12)
    @Digits(fraction = 0, integer = 12)
    private String phoneNumber;

    private String title;

    @NotNull
    @NotEmpty
    @Email
    @CompanyEmail(value = "@javacodegeeks.com")
    private String companyEmail;

	...snipped...
}

We have placed the following constraints on the fields of the IndexBacking class.

  1. @NotNull, The value of the field or property must not be null.
  2. @Size, The size of the field or property is evaluated and must match the specified boundaries. If the field or property is a String, the size of the string is evaluated. If the field or property is a Collection, the size of the Collection is evaluated. If the field or property is a Map, the size of the Map is evaluated. If the field or property is an array, the size of the array is evaluated. Use one of the optional max or min elements to specify the boundaries.
  3. @Pattern, The value of the field or property must match the regular expression defined in the regexp element.
  4. @NotEmpty, Checks whether the annotated element is not null nor empty.
  5. @Email, Checks whether the specified character sequence is a valid email address. The optional parameters regexp and flags allow to specify an additional regular expression (including regular expression flags) which the email must match.
  6. @Digits, The value of the field or property must be a number within a specified range. The integer element specifies the maximum integral digits for the number, and the fraction element specifies the maximum fractional digits for the number.
  7. @CompanyEmail, Our custom constraint.

The @Email and @NotEmpty constraints belong to the Hibernate Validator library. The Hibernate Validator is the reference implementation of Bean validation. The @CompanyEmail is our custom constraint which will be explained later. The rest belong to the Built-In Bean Validation Constraints. Check out the mentioned links for more details on the constraints.

Run the web application and input invalid data. You should see something like below:

Java EE Bean Validation Example
Java EE Bean Validation Example

6. Validating Null and Empty Strings

The Java programming language distinguishes between null and empty strings. Here is a web.xml context parameter that can save us a lot of headache. Let’s open our web.xml file. Here we have set the javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL context parameter to true. This parameter enables the JavaServer Faces implementation to treat empty strings as null. If you have a @NotNull constraint on an element, meaning that input is required. An empty string will pass this validation constraint. However, if you set the aforementioned context parameter to true, the value of the managed bean attribute is passed to the Bean Validation runtime as a null value, causing the @NotNull constraint to fail.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	version="3.1"
>
 	<context-param>
		<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
		<param-value>true</param-value>
	</context-param>
</web-app>

In our example, there are no contraints on the title field. Input the following, name: xyz, email: xyz@example.com, phone: 1234567890, company email: xyz@javacodegeeks.com, and leave title empty. We should see something like below in the console output.

null title

14:18:27,267 INFO  [stdout] (default task-3) Registering xyz, xyz@example.com, 1234567890, null, xyz@javacodegeeks.com

The title is null. Now, this time input a couple of spaces in the title field. We should see something like below in the console output.

spaces on title

14:43:26,057 INFO  [stdout] (default task-4) Registering xyz, xyz@example.com, 1234567890,    , xyz@javacodegeeks.com

Did you notice the spaces in between the phone number and the javacodegeeks email?

7. Custom Bean Validation Contraint

In our example, we want the Company email to be @javacodegeeks.com. CompanyEmail is our annotation type. To define this annotation type as a Bean Validation Constraint, we added the annotation @Constraint in its declaration.

CompanyEmail.java

package com.javacodegeeks.example.constraints;

import static java.lang.annotation.ElementType.FIELD;
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;

@Target({ FIELD })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = { CompanyEmailValidator.class })
public @interface CompanyEmail {
	String message() default "Company email does not contain {value}.";
	Class<?>[] groups() default { }; //required
	Class<? extends Payload>[] payload() default { }; //required

	String value();
}
  • @Target, Is where our annotations can be used.
  • @Retention, Specifies how the marked annotation is stored. We choose RUNTIME, so it can be used by the runtime environment.
  • @Constraint, Marks an annotation as being a Bean Validation constraint. The element validatedBy specifies the class implementing the constraint.
  • message, Defines the message that will be shown when the input data is not valid.
  • groups, Lets the developer select to split the annotations into different groups to apply different validations to each group.
  • payload, Payloads are typically used to carry metadata information consumed by a validation client.
  • value, The value that will be used to define whether the input value is valid or is not.

CompanyEmailValidator.java

package com.javacodegeeks.example.constraints;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class CompanyEmailValidator implements ConstraintValidator<CompanyEmail, String> {

	protected String companyEmailSuffix;

	@Override
	public void initialize(CompanyEmail email) {
		companyEmailSuffix = email.value();
	}

	@Override
	public boolean isValid(String email, ConstraintValidatorContext context) {
		if (email != null && email.endsWith(companyEmailSuffix)) {
			return true;
		}

		return false;
	}

}

A validator class must implement ConstraintValidator. It has two methods: initialize and isValid. The method initialize will be used to establish the necessary attributes to execute the validation — in our case, the email is “@javacodegeeks.com”. isValid is the method that received the input value and decides whether it is valid or is not. The implementation of ConstraintValidator<CompanyEmail, String> says it accepts CompanyEmail as an annotation and the input value must be a type of String.

As you might have already seen, this is how we used the custom constraint.

IndexBacking.java

    @CompanyEmail(value = "@javacodegeeks.com")
    private String companyEmail;

8. Java EE Bean Validation Example Summary

There you have it. Now you know which validation technique to use. You may choose Bean validation over JSF validation. There are many built-in validation constraints but you can also create your own. Furthermore, setting the javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL context parameter of the web deployment descriptor can hopefully reduce your validation headache. Simples! Or not?

7. Download the Source Code

This is an example about Java EE Bean Validation.

Download
You can download the source code of this example here: Java EE Bean Validation Example

Joel Patrick Llosa

I graduated from Silliman University in Dumaguete City with a degree in Bachelor of Science in Business Computer Application. I have contributed to many Java related projects at Neural Technologies Ltd., University of Southampton (iSolutions), Predictive Technologies, LLC., Confluence Service, North Concepts, Inc., NEC Telecom Software Philippines, Inc., and NEC Technologies Philippines, Inc. You can also find me in Upwork freelancing as a Java Developer.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button