Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 371 Vote(s) - 3.45 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Validation in Spring MVC in Controllers or Service Layer?

#1
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?
Reply

#2
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][1] 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][2] would nicely work with a contraption that uses Errors, while a [jackson resolver][3] would probably work nicer with a combination of [@ResponseBody][4] and some filter that catches errors and puts them in a predefined error part of the response object.


[1]:

[To see links please register here]

[2]:

[To see links please register here]

[3]:

[To see links please register here]

[4]:

[To see links please register here]

Reply

#3
In one of our previous projects, we had huge forms with very complex logic which meant a lot of validating code. So we used a third kind of solution. For every controller, we autowired a helper class.
Example:

myview <-> MyController <- MyService <- MyDAO
^
|
MyHelper

`Controllers` handled the view resolving.
`Services` handled mapping from dto-s to model objects for view and vice versa,
`DAO-s` handled database transactions and,
`Helpers` handled everything else including validation.


If now someone would have wanted to change the frontend from web to something else, it would have been a lot easier and at the same time, we didn't over-bloat the service implementation classes.
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through