0

Problem:

Accented characters cause Jackson to fail in the object mapping stage when sending a POST request from the Android application, but work fine when using the Advanced Rest Client plugin for chrome.

This leads me to believe the issue is related to how the Android code is sending the request, but I've tried adding explicit references to UTF-8 with no success. When I debug the process during execution all values seem correct.

Context:

I'm developing an application on Android that connects to a server that exposes endpoints implemented in Spring. The server is developed using Spring MVC and makes use of Google App Engine.

A specific endpoint can receive user inputted values, which may include accented characters.

The payload follows this structure, which maps to an object on the server side:

{
    "senderEmail":"<email here>",
    "token":"<token here>",
    "friendList":["<email here>"],
    "base64Value":"<base64 encoded value here>",
    "message":"รบ"
}

When this payload is sent from the REST client the server processes the request fine and returns a 200. When sending it from the Android application, the following exception is thrown:

org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver resolveException: Resolving exception from handler [public org.springframework.http.ResponseEntity<java.lang.Object> com.web.controllers.PictureController.postPic(com.web.controllers.viewobjects.PostPicRequest)]: org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Invalid UTF-8 middle byte 0x22
     at [Source: com.google.apphosting.runtime.jetty.RpcConnection$RpcRequestInput@832f7f; line: 1, column: 15] (through reference chain: com.web.controllers.viewobjects.PostPicRequest["message"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Invalid UTF-8 middle byte 0x22
     at [Source: com.google.apphosting.runtime.jetty.RpcConnection$RpcRequestInput@832f7f; line: 1, column: 15] (through reference chain: com.web.controllers.viewobjects.PostPicRequest["message"])

Code:

The Android code that sends the request (edited for public viewing):

URL url = new URL( URL_POST );
urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Accept-Encoding", ""); 

String base64Value = "blabla"

//Get JSON
JSONObject jsonObject = new JSONObject();
jsonObject.accumulate(Api.POST_PARAM_BASE64VALUE, base64Value);
jsonObject.accumulate(Api.POST_PARAM_SENDEREMAIL, senderEmail);
jsonObject.accumulate(Api.POST_PARAM_TOKEN, token);
jsonObject.accumulate(Api.POST_PARAM_MESSAGE, message);

//Make array from friends string
String[] allFriendsArray = friendList.split(",");
JSONArray friendsJsonArray = new JSONArray();
for(String x : allFriendsArray) {
    friendsJsonArray.put(x.trim());
}

jsonObject.accumulate(Api.POST_PARAM_FRIENDLIST, friendsJsonArray);
jsonObject.accumulate(Api.POST_PARAM_ISANONYMOUS, isAnonymous);

DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
wr.writeBytes(jsonObject.toString());
wr.flush();
wr.close();

int httpResponseCode = urlConnection.getResponseCode();

Got the same response when using the following code in Android:

HttpPost httpPost = new HttpPost(Api.URL_POST);
httpPost.setEntity(new StringEntity(jsonObject.toString()));
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
HttpResponse resp = new DefaultHttpClient().execute(httpPost);    

The Spring method definition, which is contained in a controller annotated with @RestController:

@RequestMapping(value= "/post", method = RequestMethod.POST)
public ResponseEntity<Object> post(@RequestBody PostRequest postRequest) { /*code here*/}
chava
  • 1
  • 2

1 Answers1

0

Found the following snippet of code ( here ) that properly encodes the payload and is received correctly on the server side too.

Thanks everyone!

    OutputStream os = urlConnection.getOutputStream();
    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
    writer.write( jsonObject.toString() );
    writer.close();
    os.close();
    int httpResponseCode = urlConnection.getResponseCode();
Community
  • 1
  • 1
chava
  • 1
  • 2