Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

typeMismatch.java.util.List when trying to set a list

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?

like image 307
ilhan Avatar asked Jul 06 '19 07:07

ilhan


People also ask

Why ArrayList does not implement add or remove method in Java?

ArrayList extends java.util.AbstractList and it does not implement add or remove method. Thus when this method is called on the list object, it calls to add or remove method of AbstractList class which throws this exception.

What is a list in Java?

A list in Java is an interface and there are many list types that implement this interface. I will use ArrayList in the first few examples, because it is the most commonly used type of list.

How to convert list to set in Java?

List to Set in Java. Given a list (ArrayList or LinkedList), convert it into a set (HashSet or TreeSet) of strings in Java. Method 1 (Simple) We simply create an list. We traverse the given set and one by one add elements to the list. // Java program to demonstrate conversion of.

How to use stream to convert set to list in Java?

If we use Stream to convert Set to List, first, we will convert Set to stream and then convert the stream to list. It works only in Java 8 or later versions. List<String> list = set.stream ().collect (Collectors.toList ()); stream (): The method stream () returns a regular object stream of a set or list.


2 Answers

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.

like image 70
buræquete Avatar answered Nov 09 '22 00:11

buræquete


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.

like image 26
Ajay Kumar Avatar answered Nov 09 '22 01:11

Ajay Kumar