0

I am developing an Android app where I need to fetch results from a MySQL database in a remote server. I have written some PHP scripts to query the database and output the results in JSON format.

The problem is that the request fetches expected results only for the first time. When I send the same request with different POST params, it returns the first result all over again. I modified the PHP script to attach the POST param in the JSON result and tried logging the POST param. It is also the same first param. If I uninstall the app from the device and re-install, again it returns the correct JSON only for the first time.

NOTE: When i run the same code with the same PHP scripts and same database on localhost (WAMPP), everything works perfect. I tried using the Google Chrome extension Postman to check the output from the remote server, it worked as expected. So, I can confirm that the problem is with my app/code.

Here's my CustomJSONObjectRequest class :

public class CustomJSONObjectRequest extends Request<JSONObject> {

private Listener<JSONObject> listener;
private Map<String, String> params;

public CustomJSONObjectRequest(String url, Map<String, String> params,
                     Listener<JSONObject> reponseListener, ErrorListener errorListener) {
    super(Method.GET, url, errorListener);
    this.listener = reponseListener;
    this.params = params;
}

public CustomJSONObjectRequest(int method, String url, Map<String, String> params,
                     Listener<JSONObject> reponseListener, ErrorListener errorListener) {
    super(method, url, errorListener);
    this.listener = reponseListener;
    this.params = params;
}

protected Map<String, String> getParams()
        throws com.android.volley.AuthFailureError {
    return params;
};

@Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
    try {
        String jsonString = new String(response.data,
                HttpHeaderParser.parseCharset(response.headers));
        return Response.success(new JSONObject(jsonString),
                HttpHeaderParser.parseCacheHeaders(response));
    } catch (UnsupportedEncodingException e) {
        return Response.error(new ParseError(e));
    } catch (JSONException je) {
        return Response.error(new ParseError(je));
    }
}

@Override
protected void deliverResponse(JSONObject response) {
    listener.onResponse(response);
}
}

And this is how I am sending the request :

            String item_name = getIntent().getExtras().getString("item_name");
            String url = getString(R.string.remote_server)+"fetch-item-list.php";

            CustomJSONObjectRequest jsObjRequest = new CustomJSONObjectRequest(Request.Method.POST, url, null, new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {


                    try {
                        Log.d("item name from intent extra", item_name); //intent extra
                        Log.d("response", response.toString()); //json response
                        Log.d("item name from response", response.getString("item_name")); //post parameter. This and the intent extra should be same

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Toast.makeText(getApplicationContext(), error.toString(), Toast.LENGTH_SHORT).show();
                }
            }) {
                @Override
                protected Map<String, String> getParams() throws AuthFailureError {
                    Map<String, String> params = new HashMap<>();

                    params.put("item_name", item_name);

                    return params;
                }

                @Override
                public Map<String, String> getHeaders() throws AuthFailureError {
                    Map<String, String> header = new HashMap<String, String>();
                    header.put("Content-Type", "application/json; charset=utf-8");
                    return header;
                }
            };



            MyVolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsObjRequest);

This is the logcat :

D/item name from intent extra: apple
D/Response: {"data":[{"item_discount":"0.00","item_price":"50.00","unique_id":"181................
D/item name from response: orange
amzer
  • 640
  • 4
  • 16
  • I don't find the error but new CustomJSONObjectRequest(Request.Method.POST, here you use POST and here using super(Method.GET, url, errorListener); GET why is that? – Amsheer Nov 10 '15 at 05:43
  • Check your server app if `orange` is the default item name reponsed if it don't get any item_name or not – BNK Nov 10 '15 at 05:59
  • @Amsheer I am calling the second constructor which takes the method as a parameter and calls the super passing it. – amzer Nov 10 '15 at 06:00
  • I mean why you use POST in one place and GET in another place? Is your method is POST or GET? – Amsheer Nov 10 '15 at 06:02
  • @BNK it's returning `orange` because i sent `orange` for the first time i requested this JSON. After that for every request it returns the same response again and again – amzer Nov 10 '15 at 06:03
  • @Amsheer POST. Please note that this same code is working fine with localhost using WAMP Server – amzer Nov 10 '15 at 06:05
  • Try the following to POST super(Method.GET, url, errorListener); . And check your input params? Maybe only first time you have values. It happens for every code one place it will work and another place it will not work for various reasons – Amsheer Nov 10 '15 at 06:08
  • Ok, try re-run your app, but this time send `banana` for example, check the response – BNK Nov 10 '15 at 06:10
  • `D/item name from intent extra: banana` `D/Response: {"data":[{"item_discount":"0.00","item_price":"50.00","unique_id":"181................` `D/item name from response: orange` – amzer Nov 10 '15 at 06:13
  • @Amsheer ok i just tried that but it seems no params are passed. – amzer Nov 10 '15 at 06:16
  • Maybe that is the issue add the required parameters. – Amsheer Nov 10 '15 at 06:19
  • @Amsheer i meant when i change it to Method.GET, no params are passed. – amzer Nov 10 '15 at 06:20
  • Don't change to GET. GET doesn't need parameter. change to POST in all the places. – Amsheer Nov 10 '15 at 06:21
  • @Amsheer originally that's what i am doing. The first constructor is never used. My problem is that i am getting the response only for the first time. I think probably the params are getting cached somewhere and replacing the request params. I've no idea – amzer Nov 10 '15 at 06:29

1 Answers1

0

I think I found the solution

Looks like the JSON response was getting cached, so the response for the first request got cached and the next requests were never sent to the server. The cached JSON response was returned for every other requests.

All I had to do was disable caching. I added the line jsObjRequest.setShouldCache(false); before adding it to the request queue.

jsObjRequest.setShouldCache(false);
MyVolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsObjRequest);

Thanks to this question.

But I still do not get it why it worked on localhost without this setting.

Community
  • 1
  • 1
amzer
  • 640
  • 4
  • 16
  • 1
    That's because the server reponse supports output caching, you can read here for more info https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=en#cache-control – BNK Nov 10 '15 at 09:19
  • Yeah! Thanks for the link. – amzer Nov 10 '15 at 09:25