Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DataBinder fails with "No primary or single unique constructor found for interface MultipartFile" #31669

Closed
mschneid opened this issue Nov 24, 2023 · 5 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: regression A bug that is also a regression
Milestone

Comments

@mschneid
Copy link

mschneid commented Nov 24, 2023

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().

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Nov 24, 2023
@snicoll
Copy link
Member

snicoll commented Nov 24, 2023

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.

@snicoll snicoll added the status: waiting-for-feedback We need additional information before we can continue label Nov 24, 2023
@jhoeller
Copy link
Contributor

jhoeller commented Nov 24, 2023

@rstoyanchev is the new check in DataBinder possibly mis-handling MultipartFile as a plain nested bind object there?

@jhoeller jhoeller added the in: web Issues in web modules (web, webmvc, webflux, websocket) label Nov 24, 2023
@sbrannen sbrannen changed the title No primary or single unique constructor found for interface ... No primary or single unique constructor found for interface Nov 24, 2023
@rstoyanchev rstoyanchev self-assigned this Nov 24, 2023
@rstoyanchev rstoyanchev changed the title No primary or single unique constructor found for interface DataBinder fails with "No primary or single unique constructor found for interface MultipartFile" Nov 24, 2023
@rstoyanchev rstoyanchev added type: bug A general bug and removed status: waiting-for-feedback We need additional information before we can continue status: waiting-for-triage An issue we've not yet triaged or decided on labels Nov 24, 2023
@rstoyanchev rstoyanchev added this to the 6.1.2 milestone Nov 24, 2023
@mschneid
Copy link
Author

mschneid commented Nov 24, 2023

@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.

@snicoll
Copy link
Member

snicoll commented Nov 24, 2023

@mschneid apologizes, we've got many report around this and I thought it could have been one more occurrence.

@rstoyanchev
Copy link
Contributor

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: regression A bug that is also a regression
Projects
None yet
Development

No branches or pull requests

5 participants