Affects: 6.0.0-M1


I tried to add bean validation annotations on a record type, but it does not work as expected.

public record CreatePostCommand(@NotEmpty @Size(min = 5) String title, @NotEmpty String content) {
}

And write a controller test with MockMvc.

  @Test
  public void testCreatePost_validationFailed() throws Exception {
      var id = UUID.randomUUID();
      when(this.posts.save(any(Post.class)))
              .thenReturn(Post.builder().id(id).title("test").build());

      var data = new CreatePostCommand("a", "a");
      this.rest.perform(post("/posts").content(objectMapper.writeValueAsBytes(data)).contentType(MediaType.APPLICATION_JSON))
              .andExpect(status().isUnprocessableEntity())
              .andExpect(jsonPath("$.code", is("validation_failed")));

      verify(this.posts, times(0)).save(any(Post.class));
      verifyNoMoreInteractions(this.posts);
  }

The test failed because the response always returned 201 status instead of the expected 422.

Comment From: sbrannen

Related Articles

  • https://www.morling.dev/blog/enforcing-java-record-invariants-with-bean-validation/
  • https://blogs.oracle.com/javamagazine/post/diving-into-java-records-serialization-marshaling-and-bean-state-validation

As a side note, the above articles advocate using ByteBuddy to instrument the constructor invocation to automatically apply validation.

Comment From: hantsy

Oh, it is still lack of support in RC1. And as planed Spring 6 will be finally released in the next month, it means bean validation on Record will not work in Spring 6 GA?

Comment From: hantsy

Verified in Spring Boot 3.0, it seems Hibernate Validator 8.0 Final adds record support, check my updated example test: https://github.com/hantsy/spring6-sandbox/blob/master/boot/src/test/java/com/example/demo/web/PostControllerTest.java#L134

Comment From: jhoeller

So I suppose this can be seen as a documentation ticket on our end now... documenting that Hibernate Validator 8.0 is needed for constraint annotations to be discovered on record types.

Comment From: snicoll

The documentation already refers to Hibernate Validator for specific usage of the API. Given that there's nothing specific to Spring here, I am going to close this.

Comment From: ybermejo

Hi,

I am new with this Java Records, can someone help me with my issue?

I have 2 Records (PointsRedemptionV2Body & RedemptionItemBody) and I declared RedemptionItemBody as an array in the first record but the problem is the validation constraints from RedemptionItemBody are not working.

public record PointsRedemptionV2Body(

String orderReferenceNumber,

@NotNull
List<RedemptionItemBody> redemptionItemList) {

}

public record RedemptionItemBody(

@Min(value = 1L)
Integer redemptionItemNumber,

@Min(value = 1L)
Integer quantity,

@NotBlank
String awardId,

String catalogId,

@NotBlank
String shortDescription,

@NotBlank
String longDescription,

@NotBlank
String awardType,

@Min(value = 0L)
@MaxPointQuantity
Integer awardPointCost,

@NotNull
@Positive
Float companyCost
) {

}

Comment From: snicoll

@ybermejo I am afraid this is the wrong place to ask. We don’t use the issue tracker for questions, please use StackOverflow or the Hibernate Validator support forum.