More User Friendly Exceptions with Spring Global Errors

We’ve been building out NixMash Spring Posts and wanted a quick solution for the common “Post Name Exists” issue for duplicate post titles. To retrieve posts-by-their-title-slug from a data table the slugs have to of course be unique.

In this post we’re going to show two ways to handle the Exception. The first is with a custom DuplicatePostNameException which we’ll insert at the Service layer, add an Exception Handler and display on a custom error page. The second more user friendly approach will be to generate a Spring Global Error.

Before going to our first example of a custom exception, one of the reasons for this post is to demonstrate how to quickly and easily generate a Spring Global Error. We talked about Global Errors before, in “User Registration Validation in Spring” for instance, where we checked for a pre-existing username and created a Global Error similar to what we’re doing today. But in that case we went the route of creating a Spring Validator for the User object. That worked great and we may in the future add a Validator for the PostDTO object, but here we’re going with the absolute minimum requirements. With that in mind, this post’s subtitle is:

How to Generate Spring MVC Global Errors on the Cheap

A Little UI Context

Before looking at our two approaches to handling duplicate post titles, here’s the Post Entry form for context. We are assuming we already have a post titled “Summernote – Super Simple WYSIWYG editor” when we click the submit button below.

First Duplicate Post Title Example: Custom Exceptions

We’ll quickly walk through the approach to handling a duplicate post title using a custom exception. We create a DuplicatePostNameException class (which we won’t show here), then throw it in the Service Layer.

We add the Exception to our Spring MVC method for adding a new post…

…so that the Exception Handler in our Spring @ControllerAdvice GlobalController picks up the error…

…and sends it back to the client on a custom error page.

All fine and good, but the user is now swearing at us for making them go back to the “Add Post” form and re-enter the post. They’re really, really not happy with us at this moment.

A More User-Friendly Approach with Global Errors

We’re used to thinking Spring Global Errors as being more extensive agents built with validators, beans and object inspections, but as I said earlier, we’re going to generate a Global Error on the cheap. The secret is calling

BindingResult.reject()

instead of

BindingResult.rejectValue()

The latter rejectValue() generates an error on the field, while reject() creates a global error.

The MVC addPost() method will show us everything we need to know. We wrap the method logic inside a single test for the pre-existence of the new Post Title (1). If it doesn’t exist we’re good and can continue processing the postDTO content. If it does exist we throw the global error (2) and return to the client.

Here’s the HTML we’ll use to display the Global Error, with assistance from Bootstrap and Thymeleaf. Notice it sits inside the <form /> since Spring needs a Binding Object.

There, MUCH better. The user has no reason to curse at us now!

Source Code Notes for this Post

All source code discussed in this post can be found in my NixMash Spring GitHub repo and viewed online here.