Search code examples
javaspringspring-boothttprequestendpoint

How to properly work with Form Data params in Spring Boot?


I am doing a migration from Google Guice and JAX-RS to Spring Boot. Prevously the method that I had looked like this:

    @POST
    @Path("/generateTable")
    public ExportResult generateTable(@FormParam("content") TableParam tableParam,
                                                      @FormParam("panel") PanelParam panelParam,
                                                      @FormParam("entityData") EntityDataParam entityDataParam,
                                                      @FormParam("drillPath") TypoParam typoParam) 

Now I need to migrate this code in Spring Boot. I have looked at the request that is reaching this endpoint on Chrome DevTools and in the payload it has form data parameters.

When rewriting the code to Spring Boot, I realised that I cannot replace @FormParam with @RequestParam, so one solution that I have is to use this one:

    @PostMapping("/generateTable")
    public ExportResult generateTable(@RequestBody MultiValueMap<String, String> formData) {

But when using this approach I need to get the parameters from the formData hashmap and parse them to the appropriate object manually. Is there a way in which this can be done automatically without me checking whether an arguments has been passed and so for the other arguments. Also another approach which I was thinking if it is possible to create a custom object containing all the params from the request and use @RequestBody to parse it automatically?

Any other approach would be of great help !


Solution

  • Rewriting the JAX-RS request to Spring Boot MVC is straightforward with @RequestParam annotation. In your case something like this:

    @PostMapping(path = "/generateTable", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    public ResponseEntity<ExportResult> generateTable(@RequestParam("content") TableParam tableParam,
                          @RequestParam("panel") PanelParam panelParam,
                          @RequestParam("entityData") EntityDataParam entityDataParam,
                          @RequestParam("drillPath") TypoParam typoParam))
    

    Additionally you need to provide the converters from String to Java objects. You can identify the necessary code in the existing classes. It was either a constructor with a single String parameter or a static method named valueOf() or fromString() or a registered implementation of ParamConverterProvider.

    Take this code and implement the Converter<S, T> interface in a Spring component. Similar to the example below. It constructs a Customer object from JSON String:

    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.core.convert.converter.Converter;
    @Component
    public class CustomerConverter implements Converter<String, Customer> {
    
        @Autowired
        private ObjectMapper mapper;
    
        @Override
        public Customer convert(String customer) {
            try {
                return mapper.readValue(customer, Customer.class);
            } catch (JsonProcessingException e) {
                throw new IllegalArgumentException(e);
            }
        }
    }