Manual Validation — Manual Validation Inside Service Methods

We had discussed in a previous lesson that mixing bean and manual validation isn’t good — it'd compel users to submit a form multiple times to see all the errors.

However, manual validation may be useful in certain situations, e.g. if you want to avoid costly database or API calls in the first cycle, or if you aren't using bean validation altogether. In such cases, you can do manual validation, i.e. just throw an exception in your service method and catch that cross-funcaionally.

But, even when doing manual validation, how to validate for multiple conditions and provide a distinct error message for each one? Throwing multiple exceptions in your code will actually throw only the first exception, putting you into the same situation: users submitting the form multiple times to see all the errors.

A solution to this would be to first accumulate all the errors into a single exception, and then throw that. Spring Lemon's MultiErrorException is such an example. Let's have a closer look at that. Basically, it has two fields:

errors holds a list of accumulated errors, and status — defaulting to UNPROCESSABLE_ENTITY — holds the response status to send.

MultiErrorException also has a few convenience methods. One of those is httpStatus, looking as below:

As you see, it's used for setting the status. Notice that it returns this, so that you can chain it with other methods. Shortly we'll see how to use it, but let's now jump to the validate method, looking as below:

In summary, it checks for a condition, and if true, adds an error to the list. To add a field level error, provide the name of the field in the fieldName parameter. Providing fieldName as null will add a form level error, and in fact there's a convenience method for that as well:

Finally, there's a go method to throw the exception, looking as below:

So, how to validate for multiple conditions using these methods? Here is an example:

In fact, LexUtils has a couple of static methods, which provide a better look by encapsulating new MultiErrorException(). They are:

Using those, our validation code would look cleaner: