The following example works with Spring Framework 6.0, but not with 6.1:
class MyForm {
private String name;
private MultipartFile file;
MyForm(String name, @Nullable MultipartFile file) {
this.name = name;
this.file = file;
}
// ...
}
@Controller
public class FileUploadController {
@PostMapping("/form")
public String handleFormUpload(MyForm form, BindingResult errors) {
if (!form.getFile().isEmpty()) {
byte[] bytes = form.getFile().getBytes();
// store the bytes somewhere
return "redirect:uploadSuccess";
}
return "redirect:uploadFailure";
}
}
The above code throws the exception java.lang.IllegalStateException: No primary or single unique constructor found for interface org.springframework.web.multipart.MultipartFile
if the file is not specified in the request.
The method DataBinder#shouldCreateObject(MethodParameter)
was introduced with #31488. I think this method should also check whether the parameter is optional or not by calling MethodParameter#isOptional()
.
Comment From: snicoll
I think this method should also check whether the parameter is optional or not by calling MethodParameter#isOptional().
I am not sure about that. Can you check that you compile your code with -parameters
, see the second paragraph of this section of the upgrade notes. And you should have seen a warning in the logs stating as much with 6.0.x
. If that doesn't help, please move that code in text into a sample we can actually run. You can attach a zip to this issue or push the code to a separate GitHub repository.
Comment From: jhoeller
@rstoyanchev is the new check in DataBinder possibly mis-handling MultipartFile
as a plain nested bind object there?
Comment From: mschneid
@snicoll But Spring Boot sets -parameters
automatically:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<parameters>true</parameters>
</configuration>
</plugin>
However, I have created a minimal, fully verifiable example here.
Comment From: snicoll
@mschneid apologizes, we've got many report around this and I thought it could have been one more occurrence.
Comment From: rstoyanchev
@mschneid, thanks for the sample. DataBinder
is detecting correctly that the parameter is optional. The issue is related to a new feature in 6.1 where we nest recursively to apply constructor binding initialization to the arguments of a constructor. Part
and MultipartFile
arguments, however, should only be looked up.