8

I am trying to set a List<Long> to an Java object.

The set function is:

ResponseEntity<String> response = bcInsertService.addNewClip(new PrmBcClipInsert()
    .setTags(Arrays.asList(new Long[]{5L, 3L}))
);

And the object is

public class PrmBcClipInsert implements Serializable {

    @ApiModelProperty(required = true)
    private List<Long> tags;

    public List<Long> getTags() {
        return tags;
    }

    public PrmBcClipInsert setTags(List<Long> tags) {
        this.tags = tags;
        return this;
    }
}

This is BcInsertService:

public class BcInsertService extends RestTemplate {
    private static final Logger log = LoggerFactory.getLogger(BcInsertService.class);

    public ResponseEntity<String> addNewClip(PrmBcClipInsert prmBcClipInsert) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        MultiValueMap<String, Object> map= new LinkedMultiValueMap<String, Object>();
        HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<MultiValueMap<String, Object>>(prmBcClipInsert.getParameters(), headers);

        ParameterizedTypeReference<StandardResponse> typeRef = new ParameterizedTypeReference<StandardResponse>() {};
        ResponseEntity<String> response = this.postForEntity( "http://localhost:8080/bc/add-clip", request , String.class );
        log.info(response.toString());
        return response;
    }

}

And it returns an error:

Field error in object 'prmBcClipInsert' on field 'tags': rejected value [[5,3]]; codes [typeMismatch.prmBcClipInsert.tags,typeMismatch.tags,typeMismatch.java.util.List,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [prmBcClipInsert.tags,tags]; arguments []; default message [tags]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.List' for property 'tags'; nested exception is java.lang.NumberFormatException: For input string: "[5,3]"]

Why the method doesn't accept a list even though it says that it accepts a list?

16
  • 1
    Failed to convert property value of type 'java.lang.String' to required type 'java.util.List' for property 'tags'; nested exception is java.lang.NumberFormatException: For input string: "[5,3]" - My guess is that this error is happening while deserializing. You are passing a string instead of an array/list. Commented Jul 6, 2019 at 7:09
  • 8
    Side note: creating an anonymous subclass just to set a field is ugly, and completely necessary. Why not just use addNewClip(new PrmBcClipInsert().setTags(Arrays.asList(5L, 3L)));? Isn't that the whole point of returning thisfrom setTags()? Commented Jul 6, 2019 at 7:18
  • Please include the full stacktrace. Commented Jul 8, 2019 at 7:13
  • 4
    I think we need a minimal reproducible example then. Commented Jul 8, 2019 at 7:18
  • 7
    There is no getParameters() method in your posted PrmBcClipInsert class, so this code is not the code producing the posted error. Commented Jul 8, 2019 at 10:30

2 Answers 2

9
+200

I was able to recreate your error case using a form validation. You are probably trying to pass a form data that is [5, 3] for the tags variable with type List<Long>, but passing with brackets break that structure, the value ought to be 5, 3...

So what I've done is;

  1. Create a dummy controller using your input;

    @Controller
    public class TestController {
    
        @PostMapping
        public ModelAndView test(@Validated @ModelAttribute final PrmBcClipInsert prmBcClipInsert, final BindingResult bindingResult) {
            final ModelAndView modelAndView = new ModelAndView();
            System.out.println(prmBcClipInsert.getTags());
            modelAndView.setViewName("test");
            return modelAndView;
        }
    }
    
  2. Pass the form with tags=[5,3], and get the following error in BindingResult;

    org.springframework.validation.BeanPropertyBindingResult: 1 errors Field error in object 'prmBcClipInsert' on field 'tags': rejected value [[5, 3]]; codes [typeMismatch.prmBcClipInsert.tags,typeMismatch.tags,typeMismatch.java.util.List,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [prmBcClipInsert.tags,tags]; arguments []; default message [tags]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.List' for property 'tags'; nested exception is java.lang.NumberFormatException: For input string: "[5,3]"]

    Which is the identical error that you were getting... So I presume either you get this PrmBcClipInsert as a form input like in my example, or you are trying to do a similar binding in some other part of your code...

  3. Pass the form with tags=5,3, no error...


There can be a custom converter to support for passing said array input with brackets in binding logic with something like;

@Component
public class LongListConverter implements Converter<String, List<Long>> {

    @Override
    public List<Long> convert(String source) {
        return Arrays.stream(StringUtils.strip(source, "[]").split(","))
                .map(StringUtils::strip)
                .map(Long::new)
                .collect(Collectors.toList());
    }
}

With this, both 5, 3 & [5, 3] can be supplied as value of tags variable.

Sign up to request clarification or add additional context in comments.

1 Comment

We have moved to send the data with JSON and send the file separately. But I'm accepting your answer since passing tags=5,3 solves the problem. I think alternative answer would be to write a custom converter for the list which implements ConverterFactory but for a List like docs.spring.io/spring/docs/4.0.x/spring-framework-reference/… however Spring's documentation is very weak.
1

All you need is a converter here. Create a List<>String converter like below (refactor the below example in your code):

@Converter
public class StringListConverter implements AttributeConverter<List<String>, String> {
    private static final String SPLIT_CHAR = ";";

    // Go nuts on List to string here...

    @Override
    public String convertToDatabaseColumn(List<String> stringList) {
        return String.join(SPLIT_CHAR, stringList.toString());
    }

    @Override
    public List<String> convertToEntityAttribute(String string) {
        return Arrays.asList(string.split(SPLIT_CHAR));
    }
}

Try it and share the outcome.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.