Getting http 400 Bad Request Error with spring and resttemplate postForObject

13,617

Solution 1

I don't know why this is the way it is, but the error was that I had to receive the @RequestBody as TblGps[] Array and not as single object!

Although i've fetched and received the same object before and received the result as single object, ...and then I posted it back to the server, and received it as array of objects ... ist it wired?

Does anybody has an explanation for this behaviour ??

    TblGps gps = (TblGps) restTemplate.getForObject(urlGET,TblGps.class);


 // alter the Object Data


 gps.setDescr("success");

      //POST Object to Service Endpoint
      TblGps gpsResult = restTemplate.postForObject(urlPOST, "POST", TblGps.class, gps);

and my Controller code

 @RequestMapping(value="/TblGps/update", method=RequestMethod.POST, consumes = "application/json",produces="application/json")
      @ResponseBody public TblGps postSingleObject(@RequestBody  TblGps[] gps){

            logger.debug("/TblGps/update: " + gps[0].getId());

              return Application.DataRepository.save(gps[0]);
        }

Solution 2

Its seems client is not setting Accept header properly. You will need to set it using something like below :-

RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
restTemplate.exchange(url, HttpMethod.GET, entity, String.class);

You can modify above code as per your need.

Share:
13,617
kamokaze
Author by

kamokaze

Java &amp; c#

Updated on June 06, 2022

Comments

  • kamokaze
    kamokaze almost 2 years

    I keep getting Bad Request HttpClient 400 Exception when executing the POST call to my Webservice. I cant figure out wether the error is originated on client or server side ... pls help me to track down this error. But since the pst call with curl is working fine i supspect that the error origins on the client side with the construction of springs resttemplate

    The GET call is working fine! Also the post call with curl is working fine

    C:\Users\pk>curl -v  -H "Accept: application/json" -H "Content-Type: application
    /json" -X POST http://127.0.0.1:8080/TblGps/update -d @json.txt
    

    Appriciate if someone can point out where i got it wrong.

    my client code is:

    when is comes to resttemplate.postForObject .... a Http 400 Bad Request Exception is thrown - the GET is working fine and the curl command line call with post is also working

        private class HttpRequestTask extends AsyncTask<Void, Void, TblGps> {
            @Override
            protected TblGps doInBackground(Void... params) {
                try {
                    final String urlGET = "http://10.0.2.2:8080/TblGps/get?id=1";
                    final String urlPOST = "http://10.0.2.2:8080/TblGps/update/";
    
    
                    RestTemplate restTemplate = new RestTemplate();
                    restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
    
                    //get Object from Service
                    TblGps gps = (TblGps) restTemplate.getForObject(urlGET,TblGps.class);
    
    
                    // alter the Object Data
                   gps.setDescr("success");
    
                  //POST Object to Service Endpoint
                  TblGps gpsResult = restTemplate.postForObject(urlPOST, "POST", TblGps.class, gps);
    
    
                 return gpsResult;
    
    
                } catch (Exception e) {
                    Log.e("REST call", e.getMessage(), e);
                }
    
                return null;
            }
    }
    }
    

    and i've also tried with restTemplate.postForEntity

     HttpHeaders headers = new HttpHeaders();
    
                headers.add("Accept", "application/json");
                headers.add("Content-Type", "application/json");
        HttpEntity ent = new HttpEntity(gps,headers);
              ResponseEntity<TblGps> out  = restTemplate.postForEntity(urlPOST, HttpMethod.POST, TblGps.class,ent);
    

    my controller code:

      @RequestMapping(value="/TblGps/update", method=RequestMethod.POST, consumes = "application/json",produces="application/json")
      @ResponseBody public TblGps post(@RequestBody  TblGps gps){
    
            logger.debug("/TblGps/update: " + gps.getId());
              System.out.println("save.............."+ gps);
              return Application.DataRepository.save(gps);
        }
    

    my console log: the mapping of the Endpoints looks also ok on console log

    2014-05-14 08:15:37.850  INFO 2280 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
    2014-05-14 08:15:41.457  INFO 2280 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/TblGps/List],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.util.List<com.pekam.TblGps> com.pekam.TblGpsController.findAll()
    2014-05-14 08:15:41.464  INFO 2280 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/TblGps/get],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public com.pekam.TblGps com.pekam.TblGpsController.findById(long)
    2014-05-14 08:15:41.471  INFO 2280 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/TblGps/update],methods=[POST],params=[],headers=[],consumes=[application/json],produces=[application/xml || application/json],custom=[]}" onto public com.pekam.TblGps com.pekam.TblGpsController.post(com.pekam.TblGps)
    2014-05-14 08:15:41.478  INFO 2280 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/*],methods=[GET || POST || DELETE || PUT || HEAD],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String com.pekam.TblGpsController.allFallback()
    2014-05-14 08:15:42.701  INFO 2280 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
    2014-05-14 08:15:42.706  INFO 2280 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
    2014-05-14 08:15:56.645  INFO 2280 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
    2014-05-14 08:15:57.551  INFO 2280 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080/http
    2014-05-14 08:15:57.665  INFO 2280 --- [           main] com.pekam.Application                    : Started Application in 46.091 seconds (JVM running for 46.681)
    

    stacktrace of exception:

    400 Bad Request
    : org.springframework.web.client.HttpClientErrorException: 400 Bad Request
        at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:76)
        at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:524)
        at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:481)
        at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:439)
        at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:317)
        at com.pekam.myandroid.MainActivity$HttpRequestTask.doInBackground(MainActivity.java:106)
        at com.pekam.myandroid.MainActivity$HttpRequestTask.doInBackground(MainActivity.java:1)
        at android.os.AsyncTask$2.call(AsyncTask.java:288)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
        at java.lang.Thread.run(Thread.java:841)
    

    here is my code of the data class:

    /**
     * The persistent class for the tblGps database table.
     * 
     */
    @Entity
    @Table(name="tblGps")
    @NamedQuery(name="TblGps.findAll", query="SELECT t FROM TblGps t")
    public class TblGps implements Serializable {
        private static final long serialVersionUID = 1L;
        private long id;
        private Timestamp date ;
        private String descr;
        private int gpsCordsX;
        private int gpsCordsY;
        private int userid;
    
        @SuppressWarnings("deprecation")
        public TblGps() {
    
    
            date= new Timestamp(0,0,0,0,0, 0, 0);
        }
    
    
        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        @Column(unique=true, nullable=false)
        public long getId() {
            return this.id;
        }
    
        public void setId(long id) {
            this.id = id;
        }
    
    
        @Column(nullable=false)
        public Timestamp getDate() {
            return this.date;
        }
    
        public void setDate(Timestamp date) {
            this.date = date;
        }
    
    
        public String getDescr() {
            return this.descr;
        }
    
        public void setDescr(String descr) {
            this.descr = descr;
        }
    
    
        @Column(nullable=false, precision=53)
        public int getGpsCordsX() {
            return this.gpsCordsX;
        }
    
        public void setGpsCordsX(int gpsCordsX) {
            this.gpsCordsX = gpsCordsX;
        }
    
    
        @Column(nullable=false, precision=53)
        public int getGpsCordsY() {
            return this.gpsCordsY;
        }
    
        public void setGpsCordsY(int gpsCordsY) {
            this.gpsCordsY = gpsCordsY;
        }
    
    
        @Column(nullable=false)
        public int getUserid() {
            return this.userid;
        }
    
        public void setUserid(int userid) {
            this.userid = userid;
        }
    
    }