1

I have a web api I made in asp.net mvc 4 which exposes CRUD operations for a database and an I'm making an android app to try and manipulate this data.

The issue I'm facing is in the json parser with the update operation which is exposed by a http PUT request (/api/products/id)

Here is the parser I'm using which I got from an example, I modified the POST section so that it does PUT instead:

public class JSONParser {

static InputStream is = null;
static JSONObject jObj = null;
static JSONArray jArr = null;
static String json = "";

// constructor
public JSONParser() {

}

// function get json from url
    // by making HTTP POST or GET method
    public JSONObject makeHttpRequest(String url, String method,
            List<NameValuePair> params) {

        // Making HTTP request
        try {

            // check for request method
            if (method == "PUT") {
                DefaultHttpClient httpClient = new DefaultHttpClient();
                HttpPut httpPut = new HttpPut(url);
                httpPut.setEntity(new UrlEncodedFormEntity(params));

                HttpResponse httpResponse = httpClient.execute(httpPut);
                HttpEntity httpEntity = httpResponse.getEntity();
                is = httpEntity.getContent();
            }
            if(method == "POST"){
                // request method is POST
                // defaultHttpClient
                DefaultHttpClient httpClient = new DefaultHttpClient();
                HttpPost httpPost = new HttpPost(url);
                httpPost.setEntity(new UrlEncodedFormEntity(params));

                HttpResponse httpResponse = httpClient.execute(httpPost);
                HttpEntity httpEntity = httpResponse.getEntity();
                is = httpEntity.getContent();

            }else if(method == "GET"){
                // request method is GET
                DefaultHttpClient httpClient = new DefaultHttpClient();
                String paramString = URLEncodedUtils.format(params, "utf-8");
                url += "?" + paramString;
                HttpGet httpGet = new HttpGet(url);

                HttpResponse httpResponse = httpClient.execute(httpGet);
                HttpEntity httpEntity = httpResponse.getEntity();
                is = httpEntity.getContent();
            }           

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    is, "iso-8859-1"), 8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
            is.close();
            json = sb.toString();
        } catch (Exception e) {
            Log.e("Buffer Error", "Error converting result " + e.toString());
        }

        // try parse the string to a JSON object
        try {
            jObj = new JSONObject(json);
        } catch (JSONException e) {
            Log.e("JSON Parser", "Error parsing data " + e.toString());
        }

        // return JSON String
        return jObj;

    }
}

When I try to do a PUT operation, the record gets updated but the app crashes with a null pointer exception as it tries to execute is = httpEntity.getContent();

I'm having problems trying to figure what is wrong exactly with this because I can't find a detailed explanation on how things are supposed to be done, all I have are the random examples I manage to find, none of which goes past GET and POST operations.

For reference, this is the asynctask that calls the parser:

class SaveProductDetails extends AsyncTask<String, Void, String> {

    @Override
    protected String doInBackground(String... args) {
        String id = mTitleText.getText().toString();
        String desc = mBodyText.getText().toString();
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair(KEY_ID, id));
        params.add(new BasicNameValuePair(KEY_DESC, desc));
        JSONParser parser = new JSONParser();
        JSONObject json = parser.makeHttpRequest(URL + id, "PUT", params);

        try {
            Integer success = json.getInt(TAG_SUCCESS);
            if (success == 1) {
                // successfully updated
                Intent i = getIntent();
                // send result code 100 to notify about product update
                setResult(100, i);
                finish();
            } else {
                // failed to update product
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return null;

    }
}

What am I doing wrong?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
MaddoScientisto
  • 189
  • 4
  • 17

1 Answers1

2

Three things (two of which are more important).

First (important), you need to determine if your request was successful prior to processing the response body. Given the structure of your code I would recommend declaring a status code variable at the beginning of your retrieval method, and setting it after each execute:

HttpResponse httpResponse = httpClient.execute(httpPut);
status = httpResponse.getStatusLine().getStatusCode();

Second (important), you need to check that your response entity is non-null before calling any methods on it. Overall, you would be better served by using the EntityUtils class to process your response.

httpEntity = httpResponse.getEntity(); // Declare httpentity outside your try/catch
is = httpEntity.getContent();          // Remove this line entirely

The entity would then be processed as such:

try {
    if(status == HttpStatus.SC_OK) {
        json = httpentity != null ?
            EntityUtils.toString(httpentity, "iso-8859-1") : null;
    } else {
        Log.e("Server responded with error status " + status);
    }
} catch (Exception e) {
    Log.e("Buffer Error", "Error converting result " + e.toString());
}

Lastly (pretty important), you should remove all the static variables in your parser class and make them local variables of your method instead.

Perception
  • 79,279
  • 19
  • 185
  • 195