Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Validation in Spring MVC in Controllers or Service Layer?

For quite some time I try to figure out where validation of user input should take place in a Spring MVC application. In many online blogs and tutorials I basically read that a controller should validate the users input and, if invalid, respond to the user by showing a page containing the error message. My current understanding of the Spring and Spring MVC layering system, however, is that a Controller is a only shallow interface between the application logic (service layer) and the "web world", allowing usage of the service layer from the web. Also, as far as I can see, Spring MVC does only provide reasonable tools for validation in a Controller.

If now validation takes place in a Controller, if at some later point I want to untie the application logic from the "web world", validation logic must be reimplemented in the new environment (e.g. a desktop application using Swing). In my opinion, the ability to decide which operations are "valid" on domain objects, and what "valid" states such objects may have, is core part of the service layer, and not the concern of some other part of the application (e.g. Controllers).

In this context, why is it "good practice" to place input validation logic in the controller layer and not the service layer?

like image 550
AlexLiesenfeld Avatar asked Jan 28 '14 14:01

AlexLiesenfeld


People also ask

Should I validate in controller or service?

As a general rule of thumb, I would say that business logic of this sort should be in the service. Controllers should be light-weight and pass on requests. Further, there may be other clients of your service, not just controllers, so this allows you to keep validation in one place.

Where does validation happen in MVC?

Validation should be in the domain layer, but it can also be used in other layers, like the UI (probably in the Controller or the View in Js) to give fast feedback to the user.

What is the use of service layer in Spring MVC?

A service layer is a layer in an application that facilitates communication between the controller and the persistence layer. Additionally, business logic is stored in the service layer. It includes validation logic in particular. The model state is used to communicate between the controller and service layers.


1 Answers

A common approach is to do validation on both places. But if you are talking about @Valid, from my experience it is nicer to put on Controllers level.

It also depends what kind of validation logic we are talking about. Let's say you have a bean:

@Data public class MyBean {     @NotNull private UUID someId;     @NotEmpty private String someName;  } 

It would make sense for this bean to be annotated with @Valid on the controller level so it doesn't even reach the service. There is no benefit to putting the @Valid on the service method, because why would you propagate it further while you can immediately in the controller decide if it is that kind of valid or not.

Then there is a second type of validation: business logic validation. Let's say for the same bean that the someId property is a timeUUid and its timestamp needs to be at most 2 days after some event occurred, in other case, the bean should be discarded by the service.

That seems like a business logic validation case, because by just looking at the bean, you wouldn't be able to validate it, unless you apply some logic to it.

Since both approaches to validation actually validate different things, it is obvious to see that each of your MVC components - Model, View and Controller, do their own validation and it should be reasonable about what it validates without introducing dependency to the other components.

As for showing the error to the user, yes, the Errors object is indeed intended to be used for bean validation at controller level, but you can design some filter that catches exceptions on any level and then pretty formats it for the user. There are many approaches to it, and I am not sure if Spring prescribes that any is better than the other.

Depending on different resolve mechanism (as in, for example, jstl or jackson or something else), you would probably be inclined to deal with validation in a different way. For example, a traditional jstl view resolver would nicely work with a contraption that uses Errors, while a jackson resolver would probably work nicer with a combination of @ResponseBody and some filter that catches errors and puts them in a predefined error part of the response object.

like image 137
Nikola Yovchev Avatar answered Oct 17 '22 21:10

Nikola Yovchev