How to validate Spring Boot Rest response?

10,260

Solution 1

Implemented response validator:

@Aspect
@Component
public class ControllerResponseValidator {

    Logger logger = Logger.getLogger(ControllerResponseValidator.class);

    @Autowired
    private Validator validator;

    @AfterReturning(pointcut = "execution(* com.example.controller.*.*(..))", returning = "result")
    public void validateResponse(JoinPoint joinPoint, Object result) {
        validateResponse(result);
    }

    private void validateResponse(Object object) {

        Set<ConstraintViolation<Object>> validationResults = validator.validate(object);

        if (validationResults.size() > 0) {

            StringBuffer sb = new StringBuffer();

            for (ConstraintViolation<Object> error : validationResults) {
                sb.append(error.getPropertyPath()).append(" - ").append(error.getMessage()).append("\n");
            }

            String msg = sb.toString();
            logger.error(msg);
            throw new RestException(HttpStatus.INTERNAL_SERVER_ERROR, msg);
        }
    }
}

Solution 2

Use @Validated on Rest Controller and @Valid on the method for which the return object has to be validated. For Example:

RestController:

@RestController
@RequestMapping("/tasks")
@Validated
public class TaskController {

    @GetMapping("/{taskId}")
    @Valid
    public TaskDTO getTask(@PathVariable UUID taskId) {
        return convertToDto(taskService.findById(taskId));
    }  

}

DTO class:

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ValidTaskDTO
public class TaskDTO {

    @FutureOrPresent
    @NotNull
    private ZonedDateTime dueDate;

    @NotBlank(message = "Title cannot be null or blank")
    private String title;

    private String description;

    @NotNull
    private RecurrenceType recurrenceType;

    @Future
    @NotNull
    private ZonedDateTime repeatUntil;

}

My return object TaskDTO has null dueDate and repeatUntil. So the error message will be as shown below:

{
  "timestamp": "2021-01-20T11:09:37.303929",
  "status": 400,
  "error": "Bad Request",
  "message": "getTask.<return value>.dueDate: must not be null, getTask.<return value>.repeatUntil: must not be null",
  "path": null
}

I hope this helps. For details on custom class level constraint, have a look at this video.

Share:
10,260
Justinas Jakavonis
Author by

Justinas Jakavonis

Updated on June 20, 2022

Comments

  • Justinas Jakavonis
    Justinas Jakavonis almost 2 years

    I have controller implemented with Spring Boot Rest:

    @RestController
    @RequestMapping("/example")
    public class ExampleController {
    
        @Autowired
        private ExampleService exampleService;
    
        @GetMapping("/{id}")
        public ExampleResponse getExample(@NotNull @PathVariable("id") String id) {
            return exampleService.getExample(id);
        }
    }
    

    And response DTO:

    public class ExampleResponse {
    
        @NotNull
        private String id;
    
        @NotNull
        private String otherStuff;
    
        // setters and getters
    }
    

    Response body is not validated. I have annotated it with @Valid but null values still pass. Request validation works well.

    How to validate response body?

  • ch271828n
    ch271828n about 3 years
    wonderful - works for me! (I wonder why nobody upvoted this excellent answer!)