Will May opened SPR-12312 and commented

Add support for being able to validate a list of objects similar to the example below, where Foo is a class which has various JSR 303 annotations on its fields:

@RequestMapping(value = "/foo", method = RequestMethod.POST)
public void insertFoos(@Valid @RequestBody List<Foo> foos) {
  ...
}

I've managed to partially implement the functionality by extending the LocalValidatorFactoryBean and setting the nested path to the current list path ([i]) while calling super.validate in a loop. This almost works apart from the fact that the BeanWrapper cannot retrieve an invalid value if one fails validation and so throws an exception while trying to throw an exception.

So, in summary, the BeanWrapper needs to be able to work directly on lists rather than only being able to work on objects containing lists.


Affects: 4.0.7

Issue Links: - #18007 @Validated support on Iterables (and implementors) - #19182 Validate values in top-level Map parameters

1 votes, 4 watchers

Comment From: spring-projects-issues

Will May commented

It's possible that this might be a duplicate or a subtask of #6751 but that appears to be more to do with Map of objects rather than Collection of objects.

Comment From: spring-projects-issues

Frédéric Camblor commented

+1 on this (just created a duplicate of the issue before finding this one -> #18007)

Comment From: spring-projects-issues

mathsworld2001 commented

I recently came across this very same issue. Some at stackoverflow claims that this should already work as expected. I still cannot make this work. Can anyone confirm the current status of this ticket?

Comment From: spring-projects-issues

Will May commented

Still doesn't work. See an example at https://github.com/wjam/spr-12312

Comment From: SumithraPrasad

@Validated with MockMVC is not working.

@RunWith(MockitoJUnitRunner.class)
@Slf4j
public class TestController {
    private MockMvc mvc;

    @Mock
    private TestService service;

    @InjectMocks
    private Controller controller;

    private ObjectMapper mapper = new ObjectMapper();

    @Before
    public void setup() { // MockMvc standalone approach mvc =
        mvc = MockMvcBuilders.standaloneSetup(controller).setValidator(validator()).setControllerAdvice(new InvoiceServiceExceptionHandler())
                .build();
    }

    @Test
    public void whenNullValue_thenReturns400() throws JsonProcessingException, Exception {

        TestDTO testDTO = new TestDTO();
        testDTO.setId(null);

        ArrayList<TestDTO> testList = new ArrayList<TestDTO>(Arrays.asList(testDTO));

        String jsonTestList = mapper.writeValueAsString(testList);


        MvcResult responseMVC = mvc.perform(post("/v1/test").content(jsonTestList).header(HttpHeaders.CONTENT_TYPE,
                MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest()).andReturn();

    }

Comment From: rstoyanchev

@SumithraPrasad, I've edited your comment to improve the formatting. You might want to check out this Mastering Markdown guide for future reference. In particular avoid use of unquoted @ which are mentions on Github.

Also if it isn't supported to begin with, then it can't work with MockMvc.

Comment From: exe-atewinkel

This is a very old issue, but I've just run into this problem. I want to validate a Collection of objects, using validation groups.

Putting @Validated({Default.class, MyValidationGroup.class}) before the collection does not trigger validation of MyValidationGroup. Apparently it should be before the type parameter of the collection (similar to @Valid, which does not support groups), but unlike @Valid, @Validated cannot be applied to a type parameter.

This makes validating a collection of objects with specific validation groups impossible. I would greatly appreciate it if something could be done to fix this.

Specifying groups for an array of objects also does not work.

Comment From: rstoyanchev

The main challenge for bean validation support on a collection of objects is representing the results. You need one BindingResult for each object being validated, while SpringValidatorAdapter is only prepared to validate one object and prepare one BindingResult.

As part of changes to add built-in web support for method validation (see #30645) for 6.1, we already support applying method validation and preparing a MethodValidationResult with separate results for each parameter. This also supports representing results from the validation of Lists and Maps of objects.

So this should already work (with the latest 6.1 milestone 4) when method validation is applied via AOP (i.e. with @Validated at the class level). For the built-in method validation however in spring-web, I expect we need to adjust the logic that decides whether to apply method validation or to validate the parameter individually as we have always done. I'm going to schedule this to experiment for RC1.

@exe-atewinkel, thanks for the additional comment. As part of the work, I'll also experiment with applying groups, and will comment further on that.

Comment From: rstoyanchev

The built-in method validation in Spring MVC and WebFlux now works for List validation with some minor changes b068742ec8803334d4d2a91484aadf60c1e8ef4f as part of the more extensive changes for #30645.