So you have a RESTful Java webapp built using Jersey, some POJO/JAXB models that you’d like to serialize using Jackson, and think it’d be sweet to validate models using annotations (JSR 303 – Bean Validation)? And you like your objects to be immutable (Effective Java Item #15). You’ve come to the right place. Hibernate Validator is the reference implementation for JSR 303 and arguably the best currently available, so we’ll use it along with Jersey and Jackson to form the backbone of this recipe.

The general idea behind the ValidatingJacksonJsonProvider is that we can annotate any of the parameters used in our resource classes with @Valid to have the object automatically validated during the Jackson JSON serialization process.

So, first, annotate your POJO/JAXB object with some constraints, like @Min(0) and @NotEmpty.

The code to implement this recipe follows. Just add this alongside your other Jersey providers (e.g., in your resources package). Its essentially a forwarding MessageBodyReader, MessageBodyWriter that delegates to the standard JacksonJsonProvider, and hooks validation into the readFrom call.

One way to make this smarter is to throw a RuntimeException that’s registered with a Jersey ExceptionMapper. Instead of always responding with a plain-text response, this will allow Jersey to handle content-negotiation and return an error response in the appropriate format. How else could you improve this technique?

10 Responses

Correct me if I’m wrong, but I don’t like injecting the JacksonProvider here. I would like to delegate the flow back to JAX-RS and not to Jackson in particular. This way this validation provider would be independent of the serializer.

It appears to be a more generic and standard way to obtain the correct MessageBodyWriter. Using your approach you might be even overriding @Consumes or @Produces annotations and forcing the use of Jackson, but I’m not sure.

Thank you very much for your post.
Looking forward to have a “plug n play” JSR-303 provider for JAX-RS. : )

@Miguel Very interesting. I didn’t consider delegating back to JAX-RS to make this more generic, but I believe that would work as well. It so happens that I only use JSON serialization in the project I extracted this from, so I never had the need… but I’ll definitely keep this in mind in the future.

Wow, that’s some hairy code in the post you linked. With mixed dependency-injection styles, ThreadLocals, and reflection-based instance creation, this would be crazy hard to unit test. But cool that it seems to work for the author, at least.

If I ever update this code to to support a generic serialization type, I’ll look at delegating back to JAX-RS and post an update here. Heck, I might just do it for fun… I sure hope that it’ll be easier than the JAXB wrapper hell he went through though.

PS – This validating provider still handles content-type negotiation appropriately because its only used for JSON requests. Notice the @Consumes and @Produces annotations on the ValidatingJacksonJsonProvider.

What I was trying to do wasn’t so simple. I ended up in an infinite loop because JAX-RS always returned my custom MessageBodyWriter. It makes sense since it always uses the first it finds. We need another thing that isn’t a MessageBodyWriter/Reader. These are for marshalling and unmarshalling purposes. JAX-RS 2.0 introduces Interceptors which maybe more suitable for cases like this (although JAX-RS 2.0 introduces Validation itself).

This is important because you probably don’t want to do the same kind of validation across your entire application. An example is when you want to do a partial update (PUT). Or, for example, an id property must be null in a POST request but non-null everywhere else.

Your MessageBodyWriter/Reader could check the method for the group class present in the annotation @ValidateRequest(groups = PartialUpdateGroup.class) and then apply the appropriate validation. See example of this annotation usage here: @ValidateRequest(groups = PartialUpdateGroup.class).

Billy – I’m using Google Guice to inject my dependencies, so that I don’t have to manually setup the object hierarchy. If you don’t like it, you can manually initialize the object. Those values should only be null if they are not injected correctly (though normally Guice throws an error if it can’t find a value to be injected).

Subscribe

About Cody A. Ray

I’m an inquisitive, tech-savvy, entrepreneurially-spirited dude. Currently, I’m a DevOps engineer at PEAK6, an entrepreneurial investment firm in downtown Chicago. This is my personal blog. Giving true meaning to the origin of the term, my blog is a catalog of my thoughts on various matters, ranging from technology tutorials to social commentary. My goal is to create insightful, […]more →