How JAX-RS Handles Validation Failure

How JAX-RS Handles Validation Failure

How to Handle Bean 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.

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 recognized 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.

Learn More

If you would like to learn more about JAX-RS why not have a look at my online video course. In this course, you will learn all about working with JAX-RS while building a RESTful APIs for an online bookshop.

What Next?

I am an instructor at Lynda.com who offer 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.

Suggested 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.

要查看或添加评论,请登录

Alex Theedom的更多文章

  • Digital Transformation will Supercharge Your Java Career

    Digital Transformation will Supercharge Your Java Career

    If you are an experienced Java developer and you want to know how to get ahead in these unprecedented times, then…

    1 条评论
  • The Top 5 New Features in Java EE 8

    The Top 5 New Features in Java EE 8

    The much-anticipated release of Java Enterprise Edition 8 boasts two exciting new APIs (JSON-Binding 1.0 and Java EE…

    1 条评论
  • New Java EE 8 Book Released

    New Java EE 8 Book Released

    Today I launch my new Java EE book: Java EE 8: Only What's New. It has taken about 5 months to write but finally its…

  • JAX-RS Video Course Promotion

    JAX-RS Video Course Promotion

    All this week I am over at the CodeRanch answering questions about JAX-RS. Come and join me in the Web Services forum…

  • What are JAX-RS Annotations?

    What are JAX-RS Annotations?

    Overview of JAX-RS Annotations (Part 3) This is a three-part series looking at the annotation that is used to implement…

  • Overview of JAX-RS Annotations (Part 2)

    Overview of JAX-RS Annotations (Part 2)

    This is a three-part series looking at the annotation that is used to implement REST endpoints. In part one of JAX-RS…

  • Overview of JAX-RS Annotations (Part 2)

    Overview of JAX-RS Annotations (Part 2)

    This is a three-part series looking at the annotation that is used to implement REST endpoints. In part one of JAX-RS…

  • Overview of JAX-RS (Part 1)

    Overview of JAX-RS (Part 1)

    The JAX-RS API forms an important part of the Java EE platforms commitment to provide standards-driven technology. The…

  • Eclipse MicroProfile: 5 Things You Need to Know

    Eclipse MicroProfile: 5 Things You Need to Know

    Optimising Enterprise Java for Microservice Architecture The Eclipse MicroProfile initiative was launched at JavaOne…

  • How to use .filter to negate the predicate

    How to use .filter to negate the predicate

    Recently there was an interesting discussion on the use of predicate negation in the .filter method on a stream by…

社区洞察

其他会员也浏览了