droid-fu icon indicating copy to clipboard operation
droid-fu copied to clipboard

NullPointerException when using disk cache and expiration time for url is reached

Open forgivegod opened this issue 14 years ago • 2 comments

First, the Stack Trace :

09-06 20:00:46.842: DEBUG/HttpCache(736): MEM cache hit for http://oscope.org/t/time.php
09-06 20:00:50.272: DEBUG/HttpCache(736): DISK cache expiration for file /data/data/org.foo/cache/cachefu/http_cache/http+oscope+org+t+time+php
09-06 20:00:54.273: WARN/System.err(736): java.lang.NullPointerException
09-06 20:00:54.283: WARN/System.err(736):     at com.github.ignition.support.http.cache.CachedHttpResponse$ResponseData.access$0(CachedHttpResponse.java:25)
09-06 20:00:54.293: WARN/System.err(736):     at com.github.ignition.support.http.cache.CachedHttpResponse.getResponseBodyAsString(CachedHttpResponse.java:55)
09-06 20:00:54.293: WARN/System.err(736):     at org.foo.AndroidTestingActivity$GetTime.doInBackground(AndroidTestingActivity.java:46)

Scenario:

  1. Use BetterHttp or IgniteHttp to get a cacheable time string from "http://oscope.org/t/time.php"
  2. Set the expiry time to something short like 1 minute
  3. Wait for expiry time to elapse and make the same call again.
  4. Watch for nullpointerexception
  5. Making the same call again gets the time from the url correctly (only after the NPE in step four occurs).

Code Samples

The Activity :



public class AndroidTestingActivity extends Activity 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        BetterHttp.setContext(this);
        // one minute expiry time 
        BetterHttp.enableResponseCache(this, 25, 1L, 1, AbstractCache.DISK_CACHE_INTERNAL);
        BetterHttp.setupHttpClient();
        ImageLoader.initialize(this);
        ImageLoader.setMaxDownloadAttempts(2);
        setContentView(R.layout.droidfu);
        super.onCreate(savedInstanceState);
        findViewById(R.id.go).setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                new GetTimeAsyncTask().execute();

            }
        });
        new GetTimeAsyncTask().execute();
    }

    private class GetTimeAsyncTask extends AsyncTask<Void, Void, String>{

        @Override
        protected String doInBackground(Void... params) {
            try {
                String url = "http://oscope.org/t/time.php";
                BetterHttpRequest request = BetterHttp.get(url, true);
                BetterHttpResponse resp =  request.send();
                String time = resp.getResponseBodyAsString();
                return time;
            } catch (ConnectException ex) {
            } catch (Exception ex) {
                ex.printStackTrace();
                Log.e("org.foo", "doInBackground:");
                Log.e("org.foo", "UNCAUGHT: " +  ex.getClass().getName () + ": " + ex.getMessage());
                Log.e("org.foo", "UNCAUGHT:" + ex.getMessage());
                Log.e("org.foo", "UNCAUGHT:" + "ex" , ex);
            }
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
            Log.w("org.foo", "result = " + result);
            TextView txt = (TextView) findViewById(R.id.text);
            if (txt != null && result!=null){
                txt.setText(result);
            }
        }

    }

XML file

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView android:id="@+id/text" android:layout_height="wrap_content"
        android:layout_width="wrap_content" />
    <Button android:id="@+id/go" android:text="go"
        android:layout_height="wrap_content" android:layout_width="wrap_content" />
</LinearLayout>

Some other Notes

  1. This doesnt occur if disk cache is not enabled.
  2. This occurs on a few devices I have (HTC Thunderbolt, Droid X, Galaxy Tab IO, and the emulator)
  3. I'm still starting to learn GIT and MAVEN. Otherwise, I'd prolly have a fix.

forgivegod avatar Sep 06 '11 21:09 forgivegod

Thanks! Will look into it

mttkay avatar Sep 06 '11 21:09 mttkay

Did some more experimenting with Droidfu library and found a possible clue for root cause.
If you check that the responseCache has that particular key(url) the npe never gets thrown.

So I guess you have to request the same resource over and over and over until the cache time expires for this to happen. Thinking about it this might be an edge case for more natural uses.

Some more example code related to above:

        protected String doInBackground(Void... params) {
            try {
                String url = "http://oscope.org/t/time.php";
                    HttpResponseCache responseCache = BetterHttp.getResponseCache();
                    if (responseCache != null){
                        ResponseData cachedData = responseCache.get(url);
                        String log = "IN cache ";
                        if (cachedData == null ){
                            log = "MISSING";
                        }
                        Log.d("org.foo", log);
                    }
                BetterHttpRequest request = BetterHttp.get(url, true);
                BetterHttpResponse resp =  request.send();
                String time = resp.getResponseBodyAsString();
                return time;
            } catch (ConnectException ex) {
            } catch (Exception ex) {
                ex.printStackTrace();
                Log.e("org.foo", "doInBackground:");
                Log.e("org.foo", "UNCAUGHT: " + ex.getClass().getName() + ": "
                        + ex.getMessage());
                Log.e("org.foo", "UNCAUGHT:" + ex.getMessage());
                Log.e("org.foo", "UNCAUGHT:" + "ex", ex);
            }
        }

I'll try to see if this is the same case for IgniteHttp as well tommorrow.

forgivegod avatar Sep 07 '11 04:09 forgivegod