0

I created a spring RestController to process fileUpload from a react js UI.

To be able to use custom validations by @Validated annotation, had to wrap the MultipartFile into a class, I named it as UploadedFile. Created my Post Handler method with argument as @ModelAttribute. Everything works fine.

validate(target, error) method in my custom validator is called and inside POST handler method, UploadedFile object has the multipart file containing the uploaded document..

Here is a perfectly working code

 @PostMapping("/file")
    public ResponseEntity<?> receiveFile(@Validated  @ModelAttribute UploadedFile file) {
  }

@Getter
@Setter
public class UploadedFile {
    MultipartFile file;
}
// one CustomValidator class and webDataBinder.addValidators(customValidator) in controller


multipart.enabled=true //in application.properties

So far everything works as expected, Problem arise when

Someone asked me that, @ModelAttribute is a spring MVC construct, as this is a microservice, which in future, apart from my React UI, will cater to other api requests too, so I should use @RequestParam instead of @ModelAttribute.

So I changed @ModelAttribute to @RequestParam as follows

  @PostMapping("/file")
    public ResponseEntity<?> receiveFile(@Validated  @RequestParam(name = "file") UploadedFile file) 

But now I get below exception

     Failed to convert value of type 
    'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile'
     to required type 'com.x.x.x.UploadedFile'; 
     nested exception is java.lang.IllegalStateException: 
     Cannot convert value of type 
    'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' 
     to required type 'com.x.x.x.UploadedFile': 
     no matching editors or conversion strategy found

If, for @RequestParam, I change type as MultipartFile instead of UploadedFile then my posthandler gets called but the custom Validator doesn't gets called by spring before handler call, I tried to use instanceOf MultiPartFile in validator supports method by still no avail.

@PostMapping(value="/file" )
    public ResponseEntity<?> receiveFile(@Validated  @RequestParam(name = "file") MultipartFile file) 

I've the work around to explicitly call the custom validator method by code as first line in POST handler, so I dont need a solution MY QUESTION IS

How come, without adding any custom @Bean or any extra external dependencies everything works fine with @ModelAttribute, but merely changing the annotation @RequestParam doesn't work.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
ThrowableException
  • 1,168
  • 1
  • 8
  • 29
  • 1
    Ignore the comment and use `@ModelAttribute` the `@RequestParam` is as much a Spring construct as the `@ModelAttribute`. What is used on the client side doesn't matter as that is all HTTP anyway, how the server handles that isn't a concern of the client and doesn't change how the server works. Also `@RequestParam` works to convert a single parameter to a type, spring doesn't know how to convert your `file` parameter to an `UploadedFile`. When using `@ModelAttribute` it will bind the `file` parameter to a property `file` on the `UploadedFile`. Both annotations are quite different beasts! – M. Deinum Jul 21 '20 at 06:38
  • @M.Deinum If needed, I'm looking for a reference PropertyEditor implementation to make this work with `@RequestParam`. but couldn't find any. – ThrowableException Jul 21 '20 at 16:29
  • You shouldn't, the person giving the comment doesn't understand how the web works. Just use `@ModelAttribute` which is designed for that. – M. Deinum Jul 21 '20 at 18:13

0 Answers0