devdar
devdar

Reputation: 5654

SpringMVC sending JSON data to the server (java)

I have a javascript array which i populate with elements the array structure is :

 var citizens1 = [{"startLat":null,"startLng":null,"socialSecurityNumber":null}];

The array gets data however i need to push this data to the server for processing. The array holds 500 records. Instead of making 500 Web Service request to the server i convert the array data to JSON string and pass all the data to the server where i process all the records at once thus making one ajax call.

I am not sure if i am passing the data correctly to the server. I am experiencing errors. Under is my code:

Javascript

 citizens1.push({startLat:marker[index].getPosition().lat(),startLng:marker[index].getPosition().lng(),socialSecurityNumber:global_citizens[index].socialSecurityNumber});

 if(citizens1.length == 500){            
     console.log('500 records saved');          
     window.clearTimeout( timerHandle);

     for(var i = 0; i < citizens1.length ; i++){
        var myJsonString = JSON.stringify(citizens1);
        //console.log(myJsonString);

         //console.log(citizens1[i].lat +',' +citizens1[i].lng+','+citizens1[i].socialSecurityNumber); 
        $.ajax({
                type:'POST',
                url:'logMovement.htm',
                contentType: "application/json; charset=utf-8",
                async: false,
                cache: false, 
                data:myJsonString,
                dataType: 'json',
                success:function(data){

                    if (data == false){
                        console.log('error occured in logging data');
                    }

                }

            });          

     }

     citizens1 = [];
 }

Controller

 @RequestMapping(value="logMovement.htm", method={RequestMethod.POST},produces = "application/json; charset=utf-8")
     public @ResponseBody Movement logMovement(@RequestBody Movement movement)throws Exception{

         logger.info("About to log movement");

         JSONObject jsonObj = JSONObject.fromObject(movement);
         ObjectMapper mapper = new ObjectMapper();

         List<Movement> move = mapper.readValue(jsonObj.toString(), new TypeReference<Movement>(){});

        logger.info(move);
        return null;

         /*if((!lat.equals(null)) || (!(lat == null)) || (!(lat.length() == 0))){
             double dLat = Double.parseDouble(lat);
             double dLng = Double.parseDouble(lng);
             int iSocialSecurityNumber = Integer.parseInt(socialSecurityNumber);

             this.markerManager.logMovement(dLat, dLng, iSocialSecurityNumber);

         }*/


     }

Movement Class

public class Movement implements Serializable{

    private List<Integer>socialSecurityNumber;
    private List<Double> startLat;
    private List<Double> startLng;
    /**
     * @param socialSecurityNumber
     * @param startLat
     * @param startLng
     */

    public Movement(){}

    public Movement(List<Integer> socialSecurityNumber, List<Double> startLat,
            List<Double> startLng) {
        super();
        this.socialSecurityNumber = socialSecurityNumber;
        this.startLat = startLat;
        this.startLng = startLng;
    }
//getters and setters

Sample of Json Data Posted to Server

I am seeing the first rows is 'null' i am not sure if this is causing the problem

[{"startLat":null,"startLng":null,"socialSecurityNumber":null},{"startLat":10.537749449700717,"startLng":-61.44420048947677,"socialSecurityNumber":198501012},{"startLat":10.537208514171011,"startLng":-61.443589321013235,"socialSecurityNumber":198501012},{"startLat":10.536667622323245,"startLng":-61.44297811322531,"socialSecurityNumber":198501012},{"startLat":10.536131483465244,"startLng":-61.442362603115384,"socialSecurityNumber":198501012},{"startLat":10.53566878133931,"startLng":-61.44168979108997,"socialSecurityNumber":198501012},{"startLat":10.535227295591238,"startLng":-61.441000943386825,"socialSecurityNumber":198501012},{"startLat":10.170058041417015,"startLng":-61.67893982108137,"socialSecurityNumber":194302025}

Error

I was looking at this SO question which dealt with the issue Required JSON parameter is not present in jQuery Datatables

org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Can not deserialize instance of com.crimetrack.business.Movement out of START_ARRAY token

org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Can not deserialize instance of com.crimetrack.business.Movement out of START_ARRAY token
 at [Source: org.apache.catalina.connector.CoyoteInputStream@72f1db9d; line: 1, column: 1]; nested exception is org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of com.crimetrack.business.Movement out of START_ARRAY token
 at [Source: org.apache.catalina.connector.CoyoteInputStream@72f1db9d; line: 1, column: 1]
    at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.readInternal(MappingJacksonHttpMessageConverter.java:127)
    at org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:153)
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:120)
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:91)
    at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:71)
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:75)
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:156)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:117)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1008)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of com.crimetrack.business.Movement out of START_ARRAY token
 at [Source: org.apache.catalina.connector.CoyoteInputStream@72f1db9d; line: 1, column: 1]
    at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:159)
    at org.codehaus.jackson.map.deser.StdDeserializationContext.mappingException(StdDeserializationContext.java:131)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeUsingCreator(BeanDeserializer.java:397)
    at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:296)
    at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:1282)
    at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:941)
    at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.readInternal(MappingJacksonHttpMessageConverter.java:124)
    ... 33 more

Upvotes: 0

Views: 4583

Answers (3)

devdar
devdar

Reputation: 5654

I made some adjustments to the movement class and the controller and this provided me with the solution. Under is the code for those whom may be interested in solving this error:

Movement.java

It is very important to have the default constructor. If this is not there json will throw errors related to application/json; charset=utf-8 not supported http 415 unsupported media.

public class Movement implements Serializable{

    private int socialSecurityNumber;
    private double startLat;
    private double startLng;
    /**
     * @param socialSecurityNumber
     * @param startLat
     * @param startLng
     */

    public Movement(){}
    /**
     * @param socialSecurityNumber
     * @param startLat
     * @param startLng
     */
    public Movement(int socialSecurityNumber, double startLat, double startLng) {
        super();
        this.socialSecurityNumber = socialSecurityNumber;
        this.startLat = startLat;
        this.startLng = startLng;
    }
//getters and setters

Controller

Since its an array of data it is important to define the @RequestBody to use a List. Also declaring a JSONArray is important to hold the list. Once that have been done you can 'get' the data based on its type. Under is the code.

@RequestMapping(value="logMovement.htm", method = {RequestMethod.POST},consumes = "application/json")
     public @ResponseBody Movement logMovement(@RequestBody List<Movement> movement)throws Exception{

         logger.info("About to log movement");

         JSONArray nameArray =(JSONArray) JSONSerializer.toJSON(movement);

         System.out.println(nameArray.size());

          for(Object js : nameArray){
              JSONObject json = (JSONObject)js;
              //System.out.println(json.get("socialSecurityNumber"));
              if((!json.get("startLat").equals(null))){     

                     this.markerManager.logMovement(json.getDouble("startLat"),json.getDouble("startLng"), json.getInt("socialSecurityNumber"));

                }
          }


        return null;    

     }   

Upvotes: 0

Madhujith
Madhujith

Reputation: 157

you can write response in the controller like this

hope this "ll be helpful

    //get "hie" string from the service class, String is in JSON format
    String hie = svc.getHierarchysvc();

    response.setContentType("application/json");

    PrintWriter out = response.getWriter();
    out.write(hie);

Upvotes: 0

David
David

Reputation: 20063

Your JSON is invalid, the values on the left hand side of the colon need to be Strings.

[
    {
        "lat": null,
        "lng": null,
        "socialSecurityNumber": null
    }
]

Also, you appear to be using the wrong annotation, @RequestBody is used to parse the contents of the JSON rather than @RequestParam which is used to get variables from a paramter like

?var=1&newvar=2

Also, in your javascript, change data:{'myData':myJsonString } to just data:myJsonString,

You should make a dumb object to populate, check out this tutorial at the bottom of the page where they populate a dumb Person object hmkcode.com/spring-mvc-json-json-to-java

Upvotes: 2

Related Questions