5

I am writing a spring websocket application with StompJS on the client side.

On the client side I am intending to send a List of objects and on the server side when it is mapping into java object, it converts itself into a LinkedHashMap

My client side code is

function stomball() {
         stompClient.send("/brkr/call", {}, JSON.stringify(listIds));
     }

Listids looks like

[{
    "path": "/a/b/c.txt",
    "id": 12
}, {
    "path": "/a/b/c/d.txt",
    "id": 13
}]

List Id object looks like

public class ListId {

    private String path;

    private Long id;

    //getters and setters...
}

The Controller looks like this

@MessageMapping("/call" )
@SendTo("/topic/showResult")
public RetObj process(List<ListId> listIds) {
   if (!listIds.isEmpty()) {
        for(ListId listId: listIds) {

        }
}

So I get a java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.blah.ListId

However when I do the same with normal Spring Controller with RestMapping it works fine, Is there anything with springs MessageMapping annotation that maps objects to java differently than the traditional way I am not sure why is not casting to ListID

Nikhil Das Nomula
  • 1,863
  • 5
  • 31
  • 50

2 Answers2

1

I changed it from a List to an Array and it works! Here is what I did

@MessageMapping("/call" )
@SendTo("/topic/showResult")
public RetObj process(ListId[] listIds) {
   if (!listIds.isEmpty()) {
        for(ListId listId: listIds) {

       }
}

Thanks to this question ClassCastException: RestTemplate returning List<LinkedHashMap> instead of List<MymodelClass>

Community
  • 1
  • 1
Nikhil Das Nomula
  • 1,863
  • 5
  • 31
  • 50
1

I know this question has already been answered but here's another solution.

To get Jackson to convert your JSON array to list you'll have to wrap it in another object and serialize/deserialize that object.

So you'll have to send following JSON to server

{
    list: [
        {
            "path": "/a/b/c.txt",
            "id": 12
        }, {
            "path": "/a/b/c/d.txt",
            "id": 13
        }
    ]
}

List is wrapped into a another object.

Following is the wrapper class

class ServiceRequest {
    private List<ListId> list;

    public List<ListId> getList() {
        if (list == null) {
            list = new ArrayList<ListId>();
        }
        return list;
    }
}

and the message method will become

@MessageMapping("/call" )
@SendTo("/topic/showResult")
public RetObj process(ServiceRequest request) {
    List<ListId> listIds = request.getList();
    if (!listIds.isEmpty()) {
        for(ListId listId: listIds) {

        }
    }
}

Test Code

import java.util.ArrayList;
import java.util.List;
import org.codehaus.jackson.map.ObjectMapper;

public class TestJackson {
    public static void main(String[] args) throws Exception {
        System.out.println("Started");
        String json = "{\"list\":[{\"path\":\"/a/b/c.txt\",\"id\":12},{\"path\":\"/a/b/c/d.txt\",\"id\":13}]}";

        ObjectMapper mapper = new ObjectMapper();

        ServiceRequest response = mapper.readValue(json.getBytes("UTF-8"), ServiceRequest.class);

        for(ListId listId : response.getList()) {
            System.out.println(listId.getId() + " : " + listId.getPath());
        }
    }

    public static class ServiceRequest {
        private List<ListId> list;

        public List<ListId> getList() {
            if (list == null) {
                list = new ArrayList<ListId>();
            }
            return list;
        }
    }

    public static class ListId {
        private String path;
        private String id;

        public String getPath() {
            return path;
        }
        public void setPath(String path) {
            this.path = path;
        }
        public String getId() {
            return id;
        }
        public void setId(String id) {
            this.id = id;
        }
    }

}

Test Output

Started
12 : /a/b/c.txt
13 : /a/b/c/d.txt
11thdimension
  • 10,333
  • 4
  • 33
  • 71