top of page
  • Writer's pictureJuan Ayala

JSR-380 Bean Validation 2.0 in AEM

I have spent years writing and reviewing code. I have seen a lot of wheel re-invetions. I have even done a few my self 🤘🏽

But as much fun as re-inventing the wheel is, it gets tiresome. And I look for off-the-shelf solutions. For example I wrote an post on Open Feign. And how to avoid writing mountains of HTTP client code.

This post is about validating user input. Something for which I have seen countless "util" classes written. This is insane, given that there is an entire implementation out there for this purpose. That is the Hibernate Validator. The reference implementation of JSR-380.

Required Dependencies

First, let's start by defining all the dependencies we will need. Open the core/pom.xml file and put this block of dependencies in it.

The first 4 dependencies are

The next 2 are another API/Implementation pair from Jakarta EE. They are for the Hibernate Validator.

And the last two are for convenience. The Jackson JSR-310 data type module because Jackson will need to work with a LocalDate. And Lombok because I don't like to write boilerplate code.

Writing A Unit Test (TDD)

Here is my happy path unit test. I set the JSON in the AEM context request. And call the doPost() method on the servlet. Passing the request & response from the context.

Writing The Servlet and Validation

Now we are going to write the servlet. It will deserialize the JSON into a Java bean. And do the validation. The bean fields get annotated with the appropriate constraint annotation. And if there are any violations, they get streamed back to the response as a JSON object.

Embedding The Dependencies

By far, the hardest part of this exercise was embedding the required dependencies. I am using an AEM Archetype Project v43. And AEM 6.5.18. This should work on AEMaaCS as well. We need to update the core/pom.xml file. Locate the bnd-maven-plugin and update its configuration.

The first 6 includeresource instructions is pretty straight forward. They will take the dependency jars and put them into our own bundle. The last includeresource is a little more interesting. Instead of copying the jar to our bundle, it will unroll it first. Unzipping and putting the contents within our own bundle.

The reason the last package needed to get unrolled was because it is a multi-release jar file. That means it contains a directory /META-INF/versions/9.

The contents of the jackson-datatype-jsr310 bundle

This caused the bnd-maven-plugin to issue the following error

Since that directory only contained one file, module-info.class, I excluded it. Because it is not needed. Hence the !/!*/module-info.class filter.

Once the bundle gets built, this is what the contents look like. You can see there all the jar files at the root. And the com.fasterxml package got unrolled.

The contents of our site bundle that contains the embedded dependencies

And here is the bundle manifest. You see the Bundle-Classpath contains the jar files. And the com.fasterxml is a Private-Package. In fact the jar files are also private to my bundle. Nothing got exposed to the OSGi container via the Export-Package header. Except only my own.

The manifest of our site bundle that contains the embedded dependencies


Here I created a simple bean called RegistrationInformation. It uses the following constraints

There are more built-in constraints definitions. These get defined by the specification. On top of those, the Hibernate Validator implementation defines additional constraints.

If any of these do not suit your needs, you can always create a custom one. To do so is simple. Create the annotation class

Followed by an implementation of the ConstraintValidator<A, T> interface. In this case I will use BooleanUtils#toBoolean(String) to see if the string is truthy

And simple annotate the bean field. Here is a short unit test.


I have set up a simple bean with the available constraints. And even defined my own. There are a lot more things you can do with the validator. Too much to cover here. There are plenty of examples out there.

The next things you may consider looking at might be

135 views0 comments


Post: Blog2_Post
bottom of page