简体   繁体   中英

Spring boot restful API validation in layered architecture

Today i have a big discussion with one of our team member about validation of RESTful API input in Controller and Service layer and i feel it is a bad day for making bigger argument. So we have a spring boot microservice application with layered architecture

Controller --> Service --> Repository

The argument is having the validation at each layer or just having the validation at Controller layer , for example we have Controller with POST request and using JSR-380 validation for input request body

Controller :

@PostMapping(value = "/", consumes = {"application/json"}, produces = {"application/json"})
public ResponseEntity<Detail> createConfig(

        @NotNull(message = "{error.message.config_detail}")
        @RequestBody @Validated Config config) {

    return new ResponseEntity<>(configService.create(config.getConfigId(), config.getTaskId()), HttpStatus.CREATED);
  }

Config : Request Body

public class Config {

@ApiModelProperty(name = "config_id", example = "1", required = true)
@NotNull(message = "{error.message.config_id}")
private Long configId;

@ApiModelProperty(name = "task_id", example = "11", required = true)
@NotNull(message = "{error.message.task_id}")
@Min(value = 0, message = "{error.message.task_id}")
@Max(value = 9999, message = "{error.message.task_id}")
private Integer taskId;

// bunch of addition fields with validations 

 }

If the validation success then calling the Service method with some properties from Config

Service :

public Detail create(@Valid @NotNull Long configId, @NotNull Integer taskId) {

   // some business logic to convert to entity and saving to database

    return repository.save(entity));
}

So if we see the above code, same validation is done at Controller and Service , So i argued that there is no need of validating in Service layer, perform the validation at controller layer and if input is wrong then throw 400 or 500 to user. But another person in team also suggest having validation in each block for whatever is used in the block, so that individual piece of code is safe (focusing on the unit instead of the integration path).

I know i might be wrong in this case, but still not able to understand the validation at each layer,(null check i agree) so it is recommended approach having validation at each level

Controller --> validation call service

Service ---> validation and call business 

Business ---> validation and call repository

Repository --> save

But what is the prefered way of validation ? according to me if Controller input is valid call Service and perform business logic and call Repository . correct me if i'm wrong so that i can follow the recommended pattern

You are right : the validation should be placed in controller, if possible. And it's make no sense in my opinion to validate the data more then 1 time. See also DRY principle https://en.wikipedia.org/wiki/Don%27t_repeat_yourself

It is situational. Some validation needs to be performed in the service layer. Say, you will need to change a state of an object, but only if certain conditions are met etc. A part from that, as a rule of thumb i follow these guidelines: If your services are publicly exposed to other services via RMI, then service layer validation is mandatory, if not go with controller level validation.

Unless you are using the services and / or repositories as libraries in other projects, too, it does not make sense to do the validation multiple times. If the controllers are the only classes accessing the additional layers there is no need for additional validation as you and your controller are the only one to access the Spring beans. You and the controller are in control of accessing the services with valid parameters.

Doing several validations has the disadvantage of writing more complex services - including unit tests. It is slower. Changing the validation will take longer as multiple layers have to be changed - including unit tests. The validations on several layers can and will differ in a matter of time.

The preferred way is to do the validation once in (or even before) the controller and writing integration tests to ensure its functionality.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM