Custom JSR 303 Bean Validation constraints for the JSR 310 New Date/Time API

With JSR 310 Java 8 finally brought us a decent date and time API. For those of you that are still using Java 7 – like I am at my current project – there is an excellent backport available, see www.threeten.org for more details. However, I’m not going to go into any details about using the new API since there are already a ton of blog posts out there about the topic. What I am going to show you in this post is how you can use the Date/Time API in conjunction with the JSR 303 Bean Validation API by writing your own custom annotations.

If you’re using both bean validation and the new date/time API you’ll probably want to use them in conjunction. The API and an implementation like Hibernate Validator only provide a handful of constraints, e.g. NotEmpty or @Pattern. However, as of yet there are no out-of-the-box constraints for JSR 310. Fortunately it is very easy to create your own constraints. As an example I will demonstrate how you can write your own @Past annotation for validating java.time.LocalDate fields.

For testing purposes we’ll start off with a very simple class that holds a date and a dateTime. These fields are supposed to represent dates in the past. Therefore they are annotated with the @Past anootation:

Next, we’ll write a very basic unit test for the @Past constraint that demonstrates our intentions: obviously besides dates that lie in the past, we’ll also want a null reference to be valid but dates in the future to be invalid, and even today should count as invalid.

Now that we’ve got the basic test set up, we can implement the constraint itself. This consists of two steps. First we’ll have to write the annotation, and then we’ll have to implement a ConstraintValidator. To start with the annotation:

As you can see, the @Past annotation is not very spectacular. The main thing to notice is the @Constraint annotations where we specify which class will be used to perform the actual validation.

The PastValidator is where all the magic happens. By implementing the ConstraintValidator interface we’re obliged to provide two methods but for our example only the isValid() method is of use, this is where we’ll perform the actual validation.

Note that we’ve used the java.time.temporal.Temporal as the type because it is the interface that both the LocalDate and LocalDateTime classes have in common. This allows us to use the same @Past for both LocalDate and LocalDateTime fields.

And that really is all there is to it. With this very basic example I’ve shown how easy it is to create your own custom JSR 303 bean validation constraint.

One Reply to “Custom JSR 303 Bean Validation constraints for the JSR 310 New Date/Time API”

Comments are closed.