BeardedCoder
BeardedCoder

Reputation: 323

FatalException using HttpClient in AsyncTask with Android

I'm at a loss here. I'm attempting to populate a List in my Activity using data pulled from a RESTful API. I've created the API layer that talks (successfully) with the API using the Apache HttpClient library (org.apache.http.client). However, when I attempted to connect the Activity with the API layer (through an AsyncTask) calamity ensued. I removed the API layer from the code in question and instead embedded the simplest example I could think of to try and isolate the problem (to no avail). Here's the code in question:

public class MyActivity extends Activity {

@Override
protected void onCreate( Bundle savedInstanceState ) {

    super.onCreate( savedInstanceState );
    setContentView( R.layout.main );
}

@Override
protected void onResume() {

    super.onResume();
    new GetEventsTask().execute();
}

private class GetEventsTask extends AsyncTask<Object, Integer, List<IEvent>> {

    @Override
    protected List<IEvent> doInBackground( Object... params ) {

        fetch();
        return null;
    }

    @Override
    protected void onPostExecute( List<IEvent> events ) {

        Toast.makeText( getApplicationContext(), "Success", Toast.LENGTH_SHORT ).show();
    }

    private void fetch() {
        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost( "https://someurl.com/login" );

        List<NameValuePair> data = new ArrayList<NameValuePair>();
        data.add( new BasicNameValuePair( "username", "hai" ) );
        data.add( new BasicNameValuePair( "password", "kthxbye" ) );

        try {
            httpPost.setEntity( new UrlEncodedFormEntity( data ) );
            CloseableHttpResponse response = client.execute( httpPost );
        } catch( Exception e ) {
            Toast.makeText( getApplicationContext(), "Caught Exception", Toast.LENGTH_SHORT ).show();
        }
    }
}

And here is the stack trace:

10-16 19:36:04.264: ERROR/AndroidRuntime(633): FATAL EXCEPTION: AsyncTask #1
    java.lang.RuntimeException: An error occured while executing doInBackground()
    at android.os.AsyncTask$3.done(AsyncTask.java:200)
    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
    at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
    at java.lang.Thread.run(Thread.java:1019)
    Caused by: java.lang.ExceptionInInitializerError
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager$InternalConnectionFactory.<init>(PoolingHttpClientConnectionManager.java:487)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:147)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:136)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:112)
    at org.apache.http.impl.client.HttpClientBuilder.build(HttpClientBuilder.java:727)
    at org.apache.http.impl.client.HttpClients.createDefault(HttpClients.java:58)
    at ca.redacted.app.MyActivity$GetEventsTask.fetch(MyActivity.java:70)
    at ca.redacted.app.MyActivity$GetEventsTask.doInBackground(MyActivity.java:49)
    at ca.redacted.app.MyActivity$GetEventsTask.doInBackground(MyActivity.java:44)
    at android.os.AsyncTask$2.call(AsyncTask.java:185)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
    ... 4 more
    Caused by: java.lang.ExceptionInInitializerError
    at org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<init>(ManagedHttpClientConnectionFactory.java:72)
    at org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<init>(ManagedHttpClientConnectionFactory.java:84)
    at org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<clinit>(ManagedHttpClientConnectionFactory.java:59)
    ... 15 more
    Caused by: java.lang.NoSuchFieldError: org.apache.http.message.BasicLineFormatter.INSTANCE
    at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<init>(DefaultHttpRequestWriterFactory.java:52)
    at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<init>(DefaultHttpRequestWriterFactory.java:56)
    at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<clinit>(DefaultHttpRequestWriterFactory.java:46)
    ... 18 more

I'm relatively new to Android programming (and haven't touched Java in a while), so any help is greatly appreciated.

Updated Based on a debug run, this is the line that is throwing the FatalException

CloseableHttpClient client = HttpClients.createDefault();

Updated Again

Switching to use the Android supplied DefaultHttpClient implementation solved the problem (in case anyone else runs into trouble using the Apache version). Still don't know what was causing me grief with the other library.

Upvotes: 2

Views: 4862

Answers (2)

codeMagic
codeMagic

Reputation: 44571

From what I see, this doesn't seem to be your current problem but will be a problem at some point. These lines

catch( Exception e ) {
        Toast.makeText( getApplicationContext(), "Caught Exception", Toast.LENGTH_SHORT ).show();

Are updating the UI and since it is called from doInBackground() it is running on a background Thread which will cause an exception. The way to handle this is to pass response to onPostExecute() and update the UI from there depending on the type of response you get.

According to the Java Documentation

this exception comes from a problem initializing a static Class. Trace back from this line

CloseableHttpClient client = HttpClients.createDefault();

and see why that is failing.

Upvotes: 1

wtsang02
wtsang02

Reputation: 18863

I assume that you have added apache libraries because HttpClients is not build-in in the Android code, see here.The reason why you are getting an runtime Exception but not compile exception I assume its because your library isn't exported with your application.

ExceptionInInitializerError

means that it failed to load a static class which is pointing to here (HttpClients):

CloseableHttpClient client = HttpClients.createDefault();

In order to fix this, you must export your external apache library with the application , in eclipse:

Project-> config build path-> select lib to export.

In addtion to that, @codeMagic pointed out that your catch clause cannot use Toast because it should run on UI thread. This doesn't cause your exception because your current code doesn't reach the try clause, but a heads up.

Upvotes: 2

Related Questions