This might be possible, and I just couldn't find the documentation or make it work, but in essence it feels like it should be possible to bind form payloads to a Java 14 record via the constructor

record Greeting(String name){}

@Controller 
class GreetingsMvcController {

  @PostMapping ("/greetings") 
  void submit (@ModelAttribute Greeting greeting) { 
    System.out.println( "the name is " + greeting.name()) ; 
  }
}

Thanks for your consideration, and I apologize if this has already been solved.

Comment From: odrotbohm

This is a visibility issue because Greeting is package protected. If you make it public, the binding works as expected. I've previously asked for this in #22600 (this comment in particular).

Comment From: jhoeller

It turns out that this is indeed a visibility issue since the Java compiler generates the implicit record constructor as package-visible if the record type itself is also package-visible. We do not insist on the type itself being public, just on the constructor being public; a custom package-visible data class with a public constructor works fine already.

Since constructor visibility is not specifically declared by the user in case of a record, this is a rather unpleasant case. I've revisited our BeanUtils.getResolvableConstructor algorithm to keep looking for a single public constructor first, but then in case of no public constructors at all to look for a single non-public constructor with arguments before resorting to a default constructor.

I'll repurpose this issue accordingly. Our general advice remains that record types should be declared public, but anyway, we'll leniently handle such non-public scenarios as of 5.3.11 - for record types as well as custom data classes with a single non-public constructor. That said, method visibility still follows JavaBean setter/getter rules; we're not going to bend those for 5.3.x at all.

Comment From: jhoeller

Addressing this at BeanUtils.getResolvableConstructor level affects DataClassRowMapper as well. I'm taking the opportunity to add actual record tests to both spring-webmvc and spring-jdbc accordingly (for 6.0 whereas 5.3.x just has tests for record-like custom data classes).