Custom validation with Bean Validation (JSR-303)

In my previous post on Bean Validation I explained how to use built-in constrains. When the standard constraints aren’t enough, you can develop your own.

Custom constraint

Let’s create a custom constraint and have it checked that the first character is an uppercase one.

package me.m1key.jsf.constraints;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Constraint(validatedBy = FirstUpperValidator.class)
public @interface FirstUpper {
 String message() default "{me.m1key.jsf.constraints.FirstUpper.message}";

 Class<?>[] groups() default {};

 Class<? extends Payload>[] payload() default {};

  • message - the error message. You can omit curly braces and just hard code it
  • groups - this is for grouping validations (if one group fails - other groups are not checked; here we use the default group)
  • payload - additional type-safe information might be carried here

Now, we need the validator.

Custom validator

package me.m1key.jsf.constraints;

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

public class FirstUpperValidator implements
     ConstraintValidator<FirstUpper, String> {

 public void initialize(FirstUpper firstUpper) {
     // See JSR 303 Section 2.4.1 for sample implementation.

 public boolean isValid(String value, ConstraintValidatorContext context) {
     if (value == null || value.length() == 0) {
         return true;
     return value.substring(0, 1)
             .equals(value.substring(0, 1).toUpperCase());

Nothing special here. Finally, the usage...

The usage

It’s identical as any other constraint.
  @Size(min = 3)
  public String getName() {
      return name;


I showed you how to write custom constraints and gave a hint about existence and purpose of groups and payloads.

Download source code for this article

Read on