I have following code where I am calling an API which is a PHP built. The code returns json stated as below which I am collecting in a stringBuilder object. Problem is its working on some carriers and on few devices with other carriers / wifi connection its throwing JSONException end of input at character 0 exception, i know this comes when input string is empty, it means stringBuilder object is empty. Problem is i don't have access to the devices on which its throwing these errors.
I am not getting on some device why following code returns empty string and on some its working fine, user has tested on 3G as well as wifi these devices are in other country on different carriers.
HttpClient httpClient = HttpClientBuilder.create().build(); HttpPost postRequest = new HttpPost(ServiceUrls.base_url + ServiceUrls.get_profile_url); JSONObject object = new JSONObject(); object.put("username", params[0]); StringEntity input = new StringEntity(object.toString()); input.setContentType("application/json"); postRequest.setEntity(input); HttpResponse response = httpClient.execute(postRequest); if (response.getStatusLine().getStatusCode() != 200) { throw new RuntimeException("Failed : HTTP error code : " + response.getStatusLine().getStatusCode()); } BufferedReader br = new BufferedReader( new InputStreamReader((response.getEntity().getContent()))); String output; StringBuilder stringBuilder = new StringBuilder(); while ((output = br.readLine()) != null) { stringBuilder.append(output); }
If it was for all API call then it was logical but doest happen for other API call, this API call returns bigger size JSON string as follows in stringbuilder
{
"status":1, "parking":{
"name":"ghgjjghghg", "cost":3, "ownerId":29, "address":"xyz pqr", "slots":4, "image":"d4bc95c1dd031685746f2c3570788acf.jpg", "details":"gjhjghjgg", "amenities":"gjhg", "id":70, "lon":73.7898023, "lat":19.9974533, "type":0, "available":1 }, "rating":0, "ratingCount":0, "owner":{
"id":29, "username":"vd@gmail.com", "password":"", "fullname":"vi hdjh", "phone":"23434fddf", "ccNum":null, "ccType":null, "type":1, "authType":1, "image":"582e3a77d76ae3203cfd6d6a346da429.jpg", "dni":"abc123", "account":"ABCBANK" } }
I have no clue whats happening , please help. Any input will be appreciated.
4 Answers
Answers 1
There is nothing unusual about the code you posted. No clues there.
Let me summarize what I think you said about the symptoms.
For some devices / carriers, a specific API call fails. But not all devices / carriers.
For the same devices / carriers as above, other API calls work, all if the time.
The client-side code is identical in all cases, apart from the URLs.
To me, this is pointing at a problem on the server side that is triggered by what the requests look like to it. But either the way, I would try to investigate this by looking at the requests and responses on the server side, and checking the server-side logs. See if there are significant differences in the requests coming from different devices / carriers. Especially the ones that work versus the ones that don't work. And see if the responses are empty when the server sends them.
Answers 2
The code can be improved by checking (before putting it in the string builder) whether the length of the content is bigger than 0.
HttpClient httpClient = HttpClientBuilder.create().build(); HttpPost postRequest = new HttpPost(ServiceUrls.base_url + ServiceUrls.get_profile_url); JSONObject object = new JSONObject(); object.put("username", params[0]); StringEntity input = new StringEntity(object.toString()); input.setContentType("application/json"); postRequest.setEntity(input); HttpResponse response = httpClient.execute(postRequest); String output; if (response.getStatusLine().getStatusCode() != 200) { throw new RuntimeException("Failed : HTTP error code : " + response.getStatusLine().getStatusCode()); } else { HttpEntity entity = response.getEntity(); if ((entity != null) && (entity.getContentLength() != 0)) { // Use writing to output stream to prevent problems with chunked responses ByteArrayOutputStream os = new ByteArrayOutputStream(); entity.writeTo(os); output = new String(os.toByteArray(),"UTF-8"); } else { // Handle case there is not content returned System.out.println("Received no content (HTTP response code " + response.getStatusLine().getStatusCode() + " , reason: " + getReasonPhrase() +")"); } }
The code above however doesn't solve the issue why you get an empty response. I its only handling the fact it is happening is a more elegant way.
I noted however that you require a username in the request. Are you sure the user exist on the device and in case of non existing user, should there be returned something else?
Answers 3
I found the theory of Leonidos usefull: http://stackoverflow.com/a/19540249/6076711
And here is my end of solution you can try using the following code.
string output = ""; while(br.ready() && (br.readLine() != null)) { output += (String.valueOf(br.readLine()))+"\n"; }
Answers 4
This highly depends on what you want to do with the StringBuilder
object. if you are calling the StringBuilder.toString()
function the generated String will be empty, if the StringBuilder
had no input. That is meant to be that way.
You could either initialize the StringBuilder
with one of these functions:
StringBuilder stringBuilder = new StringBuilder(CharSequence cs); StringBuilder stringBuilder = new StringBuilder(int initCapacity); StringBuilder stringBuilder = new StringBuilder(String s);
or add a placeholder to the StringBuilder
when it is empty:
if(stringBuilder.length() == 0){ stringBuilder.append("NO_INPUT"); }
0 comments:
Post a Comment