spring-bootspring-mvc

How to collect all fields annotated with @RequestParam into one object


I would like to gather all of my query parameters into a pojo and perform additional validation of the fields.

I have read that I can simply create an object and spring-boot will automatically set those request parameters on it.

@GetMaping public ResponseEntity<?> listEntities(@RequestParam(value = "page-number", defaultValue = "0") @Min(0) Integer pageNumber, @RequestParam(value = "page-size", defaultValue = "100") @Min(1) Integer pageSize ... )

I am thinking to create a class called RequestParamsDTO, where I'd have my query params responsible for the pagination.

But in order to have those fields set on the RequestParamsDTO, I'd have to match the name of the request param with the field name. But it won't be a valid variable name: page-size.

There must be some workaround, similar to @RequestParam's value attribute, that would set given request param on my field in the DTO.

Please advise.


Solution

  • Someone already purposed this feature before such that you can do the following .But unfortunately it is declined due to inactivity response :

    public class RequestParamsDTO{
       @RequestParam(value="page-number",defaultValue="0")
       @Min(0)
       private Integer pageNumber;
    
       @RequestParam(value = "page-size", defaultValue = "100") 
       @Min(1) 
       Integer pageSize 
    }
    

    The most similar things that you can do is using its @ModelAttribute which will resolve the parameter in the following orders:

    • From the model if already added by using Model.
    • From the HTTP session by using @SessionAttributes.
    • From a URI path variable passed through a Converter (see the next example).
    • From the invocation of a default constructor.
    • From the invocation of a “primary constructor” with arguments that match to Servlet request parameters. Argument names are determined through JavaBeans @ConstructorProperties or through runtime-retained parameter names in the bytecode.

    That means the RequestParamsDTO cannot not have any default constructor (constructor that is without arguments) .It should have a "primary constructor" which you can use @ConstructorProperties to define which request parameters are mapped to the constructor arguments :

    public class RequestParamsDTO{
        @Min(0)
        Integer pageNumber;
        @Min(1)
        Integer pageSize;
    
        @ConstructorProperties({"page-number","page-size"})
        public RequestParamsDTO(Integer pageNumber, Integer pageSize) {
            this.pageNumber = pageNumber != null ? pageNumber : 0;
            this.pageSize = pageSize != null ? pageSize : 100;
        }
    }
    

    And the controller method becomes:

    @GetMaping
    public ResponseEntity<?> listEntities(@Valid RequestParamsDTO request){
    
    }
    

    Notes: