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;
}
}
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]);
}