How to Manually Trigger JSR380 Bean Validation on a Class

Featured image for sharing metadata for article

The JSR380 standard is a great way of validating your beans in Java.

But if you're not using something like Spring Boot to orchestrate it happening automagically, it can seem a little difficult to apply it manually.

Update 2022-01-23: You may want to read How to Create and Unit Test Java Bean Validation Annotations which covers this in more depth.

Existing Code

To set the picture, let's say that we have the following classes that provide the basis for our application, and how we want to validate it.

We have the overarching interface for our classes, TypeToValidate:

package example;

@ValidField
public interface TypeToValidate {
  String getField();
}

We then have a concrete implementation which returns a hardcoded value:

package example;

public class ObjectToValidate implements TypeToValidate {
  @Override
  public String getField() {
    return "not-correct";
  }
}

We can provide our annotation, @ValidField:

package example;

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;

@Documented
@Constraint(validatedBy = ValidFieldValidator.class)
@Target(ElementType.TYPE) // allows us to annotate the interface/class itself
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidField {
  String message() default "The field didn't validate correctly";

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

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

And the associated ValidFieldValidator:

package example;

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

public class ValidFieldValidator implements ConstraintValidator<ValidField, TypeToValidate> {
  public void initialize(ValidField constraint) {}

  public boolean isValid(TypeToValidate obj, ConstraintValidatorContext context) {
    return obj.getField().equals("correct");
  }
}

Manually Triggering Validation

So we can actually perform the validation, we need to retrieve a Validator, and then we can trigger it on the concrete implementation of the class:

package example;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import org.junit.jupiter.api.Test;

class ValidFieldValidatorTest {
  @Test
  void itReturnsConstraintViolations() {
    Validator javaxValidator = Validation.buildDefaultValidatorFactory().getValidator();

    Set<ConstraintViolation<TypeToValidate>> e = javaxValidator.validate(new ObjectToValidate());
    assertThat(e.size()).isEqualTo(1);
    System.err.println(e);
  }
}

This then rightfully rejects it, as the field has failed its validation, and we receive a set of ConstraintViolations:

[ConstraintViolationImpl{interpolatedMessage='The field didn't validate correctly', propertyPath=, rootBeanClass=class example.ObjectToValidate, messageTemplate='The field didn't validate correctly'}]

Written by Jamie Tanna's profile image Jamie Tanna on , and last updated on .

Content for this article is shared under the terms of the Creative Commons Attribution Non Commercial Share Alike 4.0 International, and code is shared under the Apache License 2.0.

#blogumentation #java #jsr380 #bean-validation.

This post was filed under articles.

Interactions with this post

Interactions with this post

Below you can find the interactions that this page has had using WebMention.

Have you written a response to this post? Let me know the URL:

Do you not have a website set up with WebMention capabilities? You can use Comment Parade.