0

Situation

I am creating a @RestController with spring-mvc to handle URLs like the following:

/api/products?attributes=brand:Audi,Mercedes&attributes=sector:Cars&...

I want to extract the @RequestParam List<AttributeValues> attributes in the corresponding method.

The AttributeValues.class does have a String name and Set<String> values that is used later to retrieve the products that match this query.

Problem

I tried to use the WebArgumentResolver but this does apparently not work for Lists. I am now searching for any advice on:

  • How to implement a custom resolver for lists (multiple values for the same param)?
  • Is there a better solution for structuring the (REST) URL for such a use-case (again, multiple values for the same argument)? I could change the format.

Requirements

The Product.class has a Set<Attribute> attributes and I can therefore not use URLs like /api/products?brand=Audi,Mercedes&sector=Cars since these attributes could interfere with the properties on the Product.class.

Thank you for your help and advice.

fdomig
  • 4,417
  • 3
  • 26
  • 39

1 Answers1

1

Using @RequestParam, you cannot bind to a List<AttributeValues> since the generic type information is lost upon compilation.

You can however bind to an array: @RequestParam AttributeValues[] attributes.

If you really want a List, another possibility is to use a custom annotation and to implement a HandlerMethodArgumentResolver that checks if the parameter has that annotation, and which resolves the argument to a List.

@Override
public boolean supportsParameter(final MethodParameter parameter) {
    return parameter.hasParameterAnnotation(YourCustomAnnotation.class);
}

@Override
public Object resolveArgument(final MethodParameter parameter, final ModelAndViewContainer mavContainer,
                              final NativeWebRequest webRequest, final WebDataBinderFactory binderFactory) throws Exception {
    return ...; // a List
}
Tom Verelst
  • 15,324
  • 2
  • 30
  • 40
  • Ahhh, I am stupid. Of course the generic type info is lost in Java after compilation. Thanks for the hint. – fdomig Apr 28 '15 at 11:32
  • Hi @Tom, Hi fdomig, I cannot agree completely. Spring is somehow able to retrieve that type information. Otherwise features like \@Autowired List wouldn't work right? And I for myself make heavy use of \@PathParam for lists of enums which is working fine as well. That's why I guess, that providing a custom WebDataBinder to the Controller could do the trick. Now I'm curious and will dig deeper ;) – Ben Steinert Apr 29 '15 at 17:20
  • Nah, boring ;) The reflection meta data stores all these information as well. This [article](http://stackoverflow.com/questions/75175/create-instance-of-generic-type-in-java) can give some background on how GenericType information is indeed accessible at runtime. Btw. I meant @RequestParam in my former comment of course. Cheers Ben. – Ben Steinert Apr 29 '15 at 18:02