SpringMVC 400 Bad request JSON data - json

I have some problem with sending request to spring mvc controller.
I have got entity:
public class Person {
private String name;
private int age;
private String city;
//..getters setters
}
and SpringMvc controller:
#Controller
#RequestMapping("/companies")
public class FirmaController {
#RequestMapping(value = "/addPerson", method = RequestMethod.POST, headers = {"Content-type=application/json"})
public String addPerson(#RequestBody Person person) {
return "person";
}
}
When i would like to send request to server with curl:
curl -i -X POST -HContent-Type:application/json -HAccept:application/json http://localhost:8080/api/companies/addPerson -d "{ 'name': 'Gerry', 'age': 20, 'city': 'Sydney' }"
i have got a HTTP/1.1 400 Bad Request:
HTTP/1.1 400 Bad Request
Content-Type: text/html;charset=ISO-8859-1
Cache-Control: must-revalidate,no-cache,no-store
Content-Length: 1392
Server: Jetty(8.1.10.v20130312)
What I do wrong?

The data you send is not valid JSON. Strings have to be wrapped in double quotes " not single quotes ' like in your example.
If you don't have an old version of Spring you should use consumes = "application/json" instead of headers=....

This one is correct:
curl -i -X POST -HContent-Type:application/json
-HAccept:application/json
http://localhost:8080/api/companies/addPerson
-d '{ "name": "Gerry", "age": 20, "city": "Sydney" }'

Related

(400) Bad Request when trying to send an image to my custom AutoML model via the REST API

I'm trying to implement my custom AutoML model in C# by sending images via the REST API, but I keep getting different errors.
The one I currently have is:
The remote server returned an error: (400) Bad Request.
I have taken an image and converted into a string of bytes called byteString and have created the jsonRequest object like this:
string jsonRequest = "{\"payload\":{\"image\":{\"imageBytes\":\"" + byteString + "\"},}}";
Then I'm doing a POST request like follows:
WebRequest request = WebRequest.Create(#"https://automl.googleapis.com/v1beta1/projects/PROJECT_ID/locations/us-central1/models/MODEL_ID:predict");
request.Method = "POST";
request.ContentType = "application/json";
request.Headers.Add("Authorization", "Bearer GCLOUD_ACCESS_TOKEN");
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(jsonRequest);
}
Then when it hits request.GetResponse(); if gives me the above error with no other information.
For reference, these are the snippets taken from the bottom of the PREDICT page on my custom AutoML model:
request.json:
{
"payload": {
"image": {
"imageBytes": "YOUR_IMAGE_BYTE"
},
}
}
Execute the request:
curl -X POST -H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
https://automl.googleapis.com/v1beta1/projects/PROJECT_ID/locations/us-central1/models/MODEL_ID:predict -d #request.json
Thanks guys, been stuck on this for a while.
Can you try to base64 the byte string? This is mentioned here.
In my use case, I share my vision model to my colleagues by creating a service account for them with the right role and give them this URL for prediction:
curl -X POST -H "Authorization: Bearer add_access_token " -H "Content-Type: application/json" https://automl.googleapis.com/v1beta1/projects/id_project/locations/us-central1/models/:model_idpredict -d #path_of_file_image_in_base64
I was able to solve this with RestSharp(https://www.nuget.org/packages/RestSharp) library
Example:
var client = new RestClient("https://automl.googleapis.com/v1beta1/projects/{project-id}/locations/us-central1/models/{model-id}:predict":
var request = new RestRequest(Method.POST);
request.AddHeader("authorization", $"Bearer {Access-Token}");
request.AddHeader("content-type", "application/json");
request.AddParameter("application/json", "{\"payload\":{\"image\":{\"imageBytes\":\"{Image-Base64}""}}}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

Content-type for application includes charset

I was writing a piece of simple Java code that calls a REST API to mimic the same I did with curl. The curl command sends a POST request to a login end-point:
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{
"username": "MicroStrategy",
"password": "MyPassword",
"loginMode": 1
}' 'https://env-792.customer.cloud.microstrategy.com/MicroStrategyLibrary/api/auth/login'
When this succeeds, you get back a 204 HTTP response code and a token as an HTTP Header.
Now, with the following code, I did not get the same result and instead got a HTTP 200 and no token and no body.
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\"username\": \"MicroStrategy\", \"password\": \"MyPassword\", \"loginMode\": 1}");
Request urlrequest = new Request.Builder()
.url("https://env-792.customer.cloud.microstrategy.com/MicroStrategyLibrary/api/auth/login")
.addHeader("accept", "application/json")
.post(body)
.build();
OkHttpClient client = new OkHttpClient();
Response urlresponse = client.newCall(urlrequest).execute();
In the process of trying to understand what I was doing wrong, I ran the request through a reverse proxy (I used "Charles") and realized that the content-type set by okhttp3 was including the charset for application/json:
POST /MicroStrategyLibrary/api/auth/login HTTP/1.1
accept: application/json
Content-Type: application/json; charset=utf-8
Content-Length: 63
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/3.8.0
Host: env-792.customer.cloud.microstrategy.com
{"username": "MicroStrategy", "password": "MyPassword", "loginMode": 1}
I verified that the matching curl statement also fails
curl -X POST --header 'Content-Type: application/json; charset=utf-8' --header 'Accept: application/json' -d '{
"username": "MicroStrategy",
"password": "MyPassword",
"loginMode": 1
}' 'https://env-792.customer.cloud.microstrategy.com/MicroStrategyLibrary/api/auth/login'
Is this a known issue? (it is my understanding that the RFC for content type only allows charset for the text/* content-types; but I'm no expert in that area!)
What can I do to overwrite the Content-Type to remove the charset part?
You are passing your JSON data to RequestBody.create() using a Java String. Per the OkHttp documentation:
public static RequestBody create(#Nullable
MediaType contentType,
String content)
Returns a new request body that transmits content. If contentType is non-null and lacks a charset, this will use UTF-8.
So, the method you are using intentionally forces UTF-8, so it is likely adding the charset attribute to match.
Try using one of the other create() methods that takes a byte[] or okio.ByteString as input instead of a Java String. They are not documented as forcing UTF-8, since they are taking raw bytes as input, so it is the caller's responsibility to specify a charset only if one is actually needed:
RequestBody body = RequestBody.create(mediaType, "{\"username\": \"MicroStrategy\", \"password\": \"MyPassword\", \"loginMode\": 1}".getBytes(StandardCharsets.UTF_8));
RequestBody body = RequestBody.create(mediaType, okio.ByteString.encodeUtf8("{\"username\": \"MicroStrategy\", \"password\": \"MyPassword\", \"loginMode\": 1}"));

How to post a json for a particular parameter using CURL

I try to do a POST request which contains number of parameters. One parameetr require a JSON file. I tried several options but i face issue with json. The parameter which requires json is 'swagger'..
Here is the curl request I try.[1] But looks like this is not accepted by server. Im getting following error;
"null is not supported"}curl: (6) Could not resolve host: swaggerimpl.json
How can i post the JSON using curl for a particular parameter?
[1]
curl -X POST -b cookies $SERVER/publisher/site/blocks/item-design/ajax/add.jag -d "action=implement&name=YoutubeFeeds&visibility=public&version=1.0.0&provider=admin&endpoint_type=http&implementation_methods=http&wsdl=&wadl=&endpointType=nonsecured&production_endpoints=http://gdata.youtube.com/feeds/api/standardfeeds&implementation_methods=endpoint" -H 'Content-Type: application/json' -d 'swagger=' #swaggerimpl.json
Edit :
Curl Command
curl -X POST -b cookies $SERVER/publisher/site/blocks/item-design/ajax/add.jag -d "action=implement&name=YoutubeFeeds&visibility=public&version=1.0.0&provider=admin&endpoint_type=http&implementation_methods=http&wsdl=&wadl=&endpointType=nonsecured&production_endpoints=http://gdata.youtube.com/feeds/api/standardfeeds&implementation_methods=endpoint" -d #swagger_impl.json -d #endpointconfig_impl.json;
Error;
at java.lang.Thread.run(Thread.java:695)
Caused by: java.lang.ClassCastException: org.mozilla.javascript.NativeJavaArray cannot be cast to java.lang.String
at
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
The suspect json file
swagger={
"apiVersion": "1.0.0",
"swaggerVersion": "1.2",
"authorizations": {
"oauth2": {
"scopes": [],
"type": "oauth2"
}
},
.........
}
The cast code:
public static boolean jsFunction_updateAPIImplementation(Context cx, Scriptable thisObj,
Object[] args, Function funObj) throws Exception, ScriptException {
boolean success = false;
if (args==null||args.length == 0) {
handleException("Invalid number of input parameters.");
}
NativeObject apiData = (NativeObject) args[0]; //This cause issue
Parameter that you are adding at the end should not contain the space. But if you remove this space then '#swagger.json' will be added as a test (not the file content). If you want to pass JSON as a parameter then you can add to the file parameter name like:
swagger={..}
It looks like workaround but curl will merge every -d parameter into the request parameters and it doesn't allow unquoted spaces.

DropWizard HealthCheck Json Response

I'm using dropwizard 0.6.2 for my service. The healthcheck response from dropwizard returns plain text. And I found a question in stackoverflow which had an answer that says we can pass a ObjectMapper to a healthcheck. But I couldn't able to find a way to pass the ObjectMapper to the HealthCheck.
Is there a way to return the healthcheck response in JSON?
As of Dropwizard 0.7, the /healthcheck path returns a JSON response:
HTTP/1.1 200 OK
Cache-Control: must-revalidate,no-cache,no-store
Content-Length: 299
Content-Type: application/json
Date: Thu, 14 Aug 2014 07:55:29 GMT
{
"My custom HealthCheck":
{
"healthy": true,
"message": "your message here"
},
"deadlocks":
{
"healthy": true
},
"storage":
{
"healthy": true
}
}
The Dropwizard use the codehale HealthCheck class.
You can call Result.healthy() and passing for parameter your JSON string.
In the method that you call the healthcheck you can use:
Result.healthy("your json");

Posting JSON to REST API

I'm creating a REST API that will accept JSON requests.
I'm testing it out using CURL:
curl -i -POST -H 'Accept: application/json' -d '{"id":1,"pan":11111}' http://localhost:8080/PurchaseAPIServer/api/purchase
But getting the following error:
HTTP/1.1 415 Unsupported Media Type
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 1051
Date: Wed, 25 Apr 2012 21:36:14 GMT
The server refused this request because the request entity is in a format not supported by the requested resource for the requested method ().
When debugging it never even gets into my create action in the controller.
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import com.app.model.Purchase;
import com.app.service.IPurchaseService;
#Controller
public class PurchaseController {
#Autowired
private IPurchaseService purchaseService;
#RequestMapping(value = "purchase", method = RequestMethod.GET)
#ResponseBody
public final List<Purchase> getAll() {
return purchaseService.getAll();
}
#RequestMapping(value = "purchase", method = RequestMethod.POST)
#ResponseStatus( HttpStatus.CREATED )
public void create(#RequestBody final Purchase entity) {
purchaseService.addPurchase(entity);
}
}
UPDATE
I added Jackson config to AppConfig.java:
#Configuration
#ComponentScan(basePackages = "com.app")
public class AppConfig {
#Bean
public AnnotationMethodHandlerAdapter annotationMethodHandlerAdapter()
{
final AnnotationMethodHandlerAdapter annotationMethodHandlerAdapter = new AnnotationMethodHandlerAdapter();
final MappingJacksonHttpMessageConverter mappingJacksonHttpMessageConverter = new MappingJacksonHttpMessageConverter();
HttpMessageConverter<?>[] httpMessageConverter = { mappingJacksonHttpMessageConverter };
String[] supportedHttpMethods = { "POST", "GET", "HEAD" };
annotationMethodHandlerAdapter.setMessageConverters(httpMessageConverter);
annotationMethodHandlerAdapter.setSupportedMethods(supportedHttpMethods);
return annotationMethodHandlerAdapter;
}
}
My GETs are working correctly now:
curl -i -H "Content-Type:application/json" -H "Accept:application/json" http://localhost:8080/PurchaseAPIServer/api/purchase
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/json
Transfer-Encoding: chunked
Date: Thu, 26 Apr 2012 21:19:55 GMT
[{"id":1,"pan":111}]
But I get the following when attempting a POST:
curl -i -X POST -H "Content-Type:application/json" -H "Accept:application/json" http://localhost:8080/PurchaseAPIServer/api/purchaseMe -d "{"id":2,"pan":122}"
HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 971
Date: Thu, 26 Apr 2012 21:29:56 GMT
Connection: close
The request sent by the client was syntactically incorrect ().
My Model:
#Entity
#XmlRootElement
public class Purchase implements Serializable {
/**
*
*/
private static final long serialVersionUID = 6603477834338392140L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private Long pan;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPan() {
return pan;
}
public void setPan(Long pan) {
this.pan = pan;
}
}
Any ideas where I'm going wrong?
Thanks
As sdouglass suggested, Spring MVC automatically detects Jackson and sets up a MappingJacksonHttpMessageConverter to handle conversion to/from JSON. But I did need explicity configure the converter to get it to work as he also pointed out.
I added the following and my CURL GET requests were working..Hooray.
AppConfig.java
#Configuration
#ComponentScan(basePackages = "com.app")
public class AppConfig {
#Bean
public AnnotationMethodHandlerAdapter annotationMethodHandlerAdapter()
{
final AnnotationMethodHandlerAdapter annotationMethodHandlerAdapter = new AnnotationMethodHandlerAdapter();
final MappingJacksonHttpMessageConverter mappingJacksonHttpMessageConverter = new MappingJacksonHttpMessageConverter();
HttpMessageConverter<?>[] httpMessageConverter = { mappingJacksonHttpMessageConverter };
String[] supportedHttpMethods = { "POST", "GET", "HEAD" };
annotationMethodHandlerAdapter.setMessageConverters(httpMessageConverter);
annotationMethodHandlerAdapter.setSupportedMethods(supportedHttpMethods);
return annotationMethodHandlerAdapter;
}
}
curl -i -H "Content-Type:application/json" -H "Accept:application/json" http://localhost:8080/PurchaseAPIServer/api/purchase
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/json
Transfer-Encoding: chunked
Date: Thu, 26 Apr 2012 21:19:55 GMT
[{"id":1,"pan":111}]
But the following CURL POST was still not working (Never hitting the controller action and giving no console debug info.
curl -i -X POST -H "Content-Type:application/json" http://localhost:8080/PurchaseAPIServer/api/purchaseMe -d "{"id":2,"pan":122}"
HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 971
Date: Thu, 26 Apr 2012 21:29:56 GMT
Connection: close
The request sent by the client was syntactically incorrect ().
So I added Logback to get some detailed debugging started.
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>/home/thomas/springApps/purchaseapi.log</file>
<encoder>
<pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n
</pattern>
</encoder>
</appender>
<logger name="org.hibernate" level="DEBUG" />
<logger name="org.springframework" level="TRACE" />
<logger name="org.springframework.transaction" level="INFO" />
<logger name="org.springframework.security" level="INFO" /> <!-- to debug security related issues (DEBUG) -->
<logger name="org.springframework.web.servlet.mvc" level="TRACE" /> <!-- some serialization issues are at trace level here: org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod -->
<!-- our service -->
<logger name="com.app" level="DEBUG" />
<!-- <logger name="com.app" level="INFO" /> --><!-- to follow if setup is being executed -->
<root level="INFO">
<appender-ref ref="FILE" />
</root>
</configuration>
Adding TRACE level debugging to org.springframework.web.servlet.mvc gave me the answer to the problem.
2012-04-28 14:17:44,579 DEBUG [http-bio-8080-exec-3] o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor [AbstractMessageConverterMethodArgumentResolver.java:117] Reading [com.app.model.Purchase] as "application/json" using [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter#74a14fed]
2012-04-28 14:17:44,604 TRACE [http-bio-8080-exec-3] o.s.w.s.m.m.a.ServletInvocableHandlerMethod [InvocableHandlerMethod.java:159] Error resolving argument [0] [type=com.app.model.Purchase]
HandlerMethod details:
Controller [com.app.controller.PurchaseController]
Method [public void com.app.controller.PurchaseController.create(com.app.model.Purchase)]
org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Unexpected character ('p' (code 112)): was expecting double-quote to start field name
I changed my CURL POSTs to the following an it all worked:
curl -i -X POST -H "Content-Type:application/json" http://localhost:8080/PurchaseAPIServer/api/purchase -d '{"pan":11111}'
HTTP/1.1 201 Created
Server: Apache-Coyote/1.1
Content-Length: 0
Date: Sat, 28 Apr 2012 13:19:40 GMT
Hopefully someone finds this useful.
If I recall correctly the Spring docs say that Spring MVC will automatically detect Jackson on the classpath and set up a MappingJacksonHttpMessageConverter to handle conversion to/from JSON, but I think I have experienced situations where I had to manually/explictly configure that converter to get things to work. You may want to try adding this to your MVC config XML:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
</list>
</property>
</bean>
UPDATE: It was this plus properly formatting the JSON being posted, see https://stackoverflow.com/a/10363876/433789
Its 2014 and I wanted to add a few updates to this question which helped me solve the same problem.
Code update to replace deprecated AnnotationMethodHandlerAdapter in Spring 3.2
#Configuration
public class AppConfig {
#Bean
public RequestMappingHandlerAdapter annotationMethodHandlerAdapter()
{
final RequestMappingHandlerAdapter annotationMethodHandlerAdapter = new RequestMappingHandlerAdapter();
final MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter = new MappingJackson2HttpMessageConverter();
List<HttpMessageConverter<?>> httpMessageConverter = new ArrayList<HttpMessageConverter<?>>();
httpMessageConverter.add(mappingJacksonHttpMessageConverter);
String[] supportedHttpMethods = { "POST", "GET", "HEAD" };
annotationMethodHandlerAdapter.setMessageConverters(httpMessageConverter);
annotationMethodHandlerAdapter.setSupportedMethods(supportedHttpMethods);
return annotationMethodHandlerAdapter;
}
}
HTTP/1.1 415 Unsupported Media Type error
After spending many hours trying to figure out why I am STILL GETTING a 415 error even after adding the correct JSON configuration I finally realized that the problem was NOT with the server side but with the client side. In order for Spring to accept your JSON you MUST make sure that you are sending both "Content-Type : application/json" and "Accept: application/json" as part of your http headers. for me specifically it was an android application HttpUrlConnection which I had to set as:
public static String doPost(final String urlString,final String requestBodyString) throws IOException {
final URL url = new URL(urlString);
final HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
urlConnection.setReadTimeout(10000 /* milliseconds */);
urlConnection.setConnectTimeout(15000 /* milliseconds */);
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("POST");
urlConnection.setChunkedStreamingMode(0);
urlConnection.connect();
final PrintWriter out = new PrintWriter(urlConnection.getOutputStream());
out.print(requestBodyString);
out.close();
final InputStream in = new BufferedInputStream(urlConnection.getInputStream());
final String response = readIt(in);
in.close(); //important to close the stream
return response;
} finally {
urlConnection.disconnect();
}
}
Try adding a descriptor of what's in your POST request. That is, add to curl the header:
Content-Type: application/json
If you don't add it, curl will use the default text/html regardless of what you actually send.
Also, in PurchaseController.create() you have to add that the type accepted is application/json.
I had the same problem, which was solved by two changes in my code :
Missing #PathVariable in my method argument, my method didn't have any
Following method in my SpringConfig class since the one I had with handler interceptor was deprecated and giving some issue:
public RequestMappingHandlerAdapter RequestMappingHandlerAdapter()
{
final RequestMappingHandlerAdapter requestMappingHandlerAdapter = new RequestMappingHandlerAdapter();
final MappingJacksonHttpMessageConverter mappingJacksonHttpMessageConverter = new MappingJacksonHttpMessageConverter();
final String[] supportedHttpMethods = { "POST", "GET", "HEAD" };
requestMappingHandlerAdapter.getMessageConverters().add(0, mappingJacksonHttpMessageConverter);
requestMappingHandlerAdapter.setSupportedMethods(supportedHttpMethods);
return requestMappingHandlerAdapter;
}
Here is a unit test solution similar to yoram givon's answer - https://stackoverflow.com/a/22516235/1019307.
public class JSONFormatTest
{
MockMvc mockMvc;
// The controller used doesn't seem to be important though YMMV
#InjectMocks
ActivityController controller;
#Before
public void setup()
{
MockitoAnnotations.initMocks(this);
this.mockMvc = standaloneSetup(controller).setMessageConverters(new MappingJackson2HttpMessageConverter())
.build();
}
#Test
public void thatSaveNewDataCollectionUsesHttpCreated() throws Exception
{
String jsonContent = getHereJSON02();
this.mockMvc
.perform(
post("/data_collections").content(jsonContent).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)).andDo(print()).andExpect(status().isCreated());
}
private String getHereJSON01()
{
return "{\"dataCollectionId\":0,\"name\":\"Sat_016\",\"type\":\"httpUploadedFiles\"," ...
}
}
Run the unit test and the print() should print out the MockHttpServletRequest including the Exception.
In Eclipse (not sure about how to do this in other IDEs), click on the Exception link and a properties dialog for that exception should open. Tick the 'enabled' box to break on that exception.
Debug the unit test and Eclipse will break on the exception. Inspecting it should reveal the problem. In my case it was because I had two of the same entity in my JSON.
I experienced once and finally solved it by adding the jar file jackson-mapper-asl.jar. Go check if you have included all these dependencies although the exception itself does not tell u that.
And you really don't need to explicitly configure the bean, and you don't need to put "consumes" in #RequestMapping statement. I'm using Spring 3.1 btw.
contentType : "application/json" is the only one you need to configure. yes, client side.
Try to add the following code in your app configuration
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
</mvc:message-converters>
I had the same problem and I resolved it.
1 add MappingJackson2HttpMessageConverter as described in that thread (see also section 4 http://www.baeldung.com/spring-httpmessageconverter-rest)
2 use correct command (with escape symbols):
curl -i -X POST -H "Content-Type:application/json" -d "{\"id\":\"id1\",\"password\":\"password1\"}" http://localhost:8080/user