News Ticker

Handle Bean Validation Failure

Java EE JAX-RS How to handle bean validation failures Java EE JAX-RS How to handle bean validation failures

How JAX-RS Handles Validation Failure

A bean validation failure results is a “400 Bad Request” response from the server. Let’s learn how to respond to the client with a more informative response.

Two Ways to Handle Failures

Two technique to report data integrity violations to the client are:

  • respond to the client with a list of problem fields in a custom key-value pair HTTP header and
  • use the response’s body to encapsulate the error response.

Both techniques have their pros and cons. The choice you make will depend on your business model and clients requirements. In either case, you need to document it well, so that a front end developer knows how to use the error response.

JAX-RS_manage_validation_failures

Learn Bean Validation with JAX-RS

Custom Key-Value Pair HTTP Header

Let’s look at the first technique.

I am going to present one way to handle the list of problem fields in the response body. As there is no accepted convention you are free to design your own structure.

I will use is a map of the property names and a message detailing what caused the validation failure.

Implement an Exception Manager

In both cases, we must implement an exception manager for the ConstraintViolationException. This exception contains a set of ConstraintViolation objects each representing the violation.

The Constraint Violation Exception

The ConstraintViolation instance contains a lot of useful information about the violation, such as the field name and the violation message. We can use this information to construct a response to the client. To do so, extract the field names and the error messages, turning the set into a stream, and collecting it to a map like so.

final Map<String, String> errorResponse =
    exception.getConstraintViolations()
      .stream()
      .collect(Collectors.toMap(o -> o.getPropertyPath().toString(), o -> o.getMessage()));

Add Errors to Response Body

We then wrap the map in a custom POJO which has one field, a map. I call the custom POJO DataIntegrityValidation. Then add it to the response body in the same way we have done so before.

return Response
         .status(Response.Status.BAD_REQUEST)
         .entity(new DataIntegrityValidation(errorResponse))
         .build();

Now the response HTTP body will contain a response similar to that which you see here.

{
  "errorResponse": {
  "entry": [{
      "key": "description",
      "value": "size must be between 100 and 2147483647"
    },
    {
      "key": "published",
      "value": "must be in the past"
    },
    {
      "key": "link",
      "value": "must match \"^(https?:\\/\\/)?([\\da-z\\.-]+)\\.([a-z\\.]{2,6})([\\/\\w \\.-]*)*\\/?$\""
    }]
 }
}

You will notice that there is a message for each bean violation. The Bean Validation API adds this for us, so we don’t have to.

However, we can customize this messages. Pass the custom message to the constraint annotations as metadata. It is possible to internationalize it so that the response appears in the client’s own language. This is beyond the scope of this article, but I encourage you to seek out examples of how to do this.

Encapsulate the Error Response

Let’s look at the second way to report violation issues to the client.

This way collects that same information as before and puts it in a custom HTTP header field. As before, extract violation data from the ConstraintViolationException and produce a comma separated String of the errors.

final String message = 
    exception
      .getConstraintViolations()
      .stream()
      .map(cv -> extractPropertyName(cv.getPropertyPath().toString()) + " : " + cv.getMessage())
      .collect(Collectors.joining(", "));

we can then add this to the response:

return Response
         .status(Response.Status.BAD_REQUEST)
         .header("X-Validation-Failure", message)
         .build();

Use a Custom Header

The response includes the custom header “X-Validation-Failure”, whose value is the message string. It is the convention to prefix custom headers with a capital X followed by a string that describes the headers purpose.

This then adds the following string to the HTTP header response.

link : must match "^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$", 
published : must be in the past, 
description : size must be between 100 and 2147483647

You will see that it contains the same data as the previous example.

Error Handling in the Wild

It’s all well and good talking about how to do this in an article but how is it done in the real world?

Let’s examine one real-world example: the National Bank of Belgium. They have approached the issue of error handling an excellent way. Firstly, they have recognised the need to present a user-friendly face to the client that consumes the web resource and secondly, they have adopted a standard and logical approach to reporting those errors. 

See for yourself an example of the JSON error message that is sent to a client when something goes wrong. Thanks to Sébastien Dubois for this example.

What Next?

Lynda.com offers online video training for a wide range of Java EE technologies. The ideal course for someone just starting out in enterprise Java is the Learning Java Enterprise Edition presented by myself. The course is just over 2hrs and covers all the most important Java EE APIs including JAX-RS for RESTful APIs, JavaServerFaces, Enterprise Java Beans and much more.

Once you have completed this course you can dive deeper into the Java the Java EE APIs and take a course on how to build a RESTful API with JAX-RS, build a chat application with WebSocket API and handle JSON with Java EE’s own JSON-Processing API. There are more courses coming so why not take a take a look and get ready to give your Java EE career a boost.

Further Reading

I blog regularly about Java EE on readlearncode.com and have just posted a series of articles examining the JAX-RS API in more detail and answering the question What is javax.ws.rs.core.context?. It is a five part series digging deeper into the multiple uses of the @Context annotation.

If you want to boost your knowledge of this technology, my articles on working with MediaTypes and JAX-RS and Resource Entities, examine this essential API in more detail.

 

1 Comment on Handle Bean Validation Failure

  1. Hi admin, i must say you have hi quality posts here.
    Your blog should go viral. You need initial traffic boost only.
    How to get it? Search for; Mertiso’s tips go viral

8 Trackbacks / Pingbacks

  1. Java EE: Past, Present & Future Boost your career with professional Java EE video course and tutorials. Learn all the technologies required to develop enterprise grade applications. Professional Java EE Video Training and Tutorials
  2. What is javax.ws.rs.core.context? [ Part 2 ] Boost your career with professional Java EE video course and tutorials. Learn all the technologies required to develop enterprise grade applications. Professional Java EE Video Training and Tutorials
  3. What is javax.ws.rs.core.context? [ Part 3 ] Boost your career with professional Java EE video course and tutorials. Learn all the technologies required to develop enterprise grade applications. Professional Java EE Video Training and Tutorials
  4. What is javax.ws.rs.core.context? [ Part 4 ] Boost your career with professional Java EE video course and tutorials. Learn all the technologies required to develop enterprise grade applications. Professional Java EE Video Training and Tutorials
  5. What is javax.ws.rs.core.context? [ Part 1 ] Boost your career with us Professional Java EE Video Training and Tutorials
  6. JAX-RS: What is @Context? Boost your career with us Professional Java EE Video Training and Tutorials
  7. JAX-RS List Generic Type Erasure Boost your career with us Professional Java EE Video Training and Tutorials
  8. Eclipse MicroProfile: 5 Things You Need to Know

Leave a Reply

%d bloggers like this: