javaandroidretrofitrobospice

RoboSpice throwing okhttp exceptions


I use RoboSpice-Retrofit for calling my server REST api which has been working without problems until a few days ago when every single call now throws an exception, Example:

D/Retrofit: java.lang.NoSuchMethodError: No direct method <init>(Lcom/squareup/okhttp/OkHttpClient;Lcom/squareup/okhttp/Request;ZZZLcom/squareup/okhttp/Connection;Lcom/squareup/okhttp/internal/http/RouteSelector;Lcom/squareup/okhttp/internal/http/RetryableSink;Lcom/squareup/okhttp/Response;)V in class Lcom/squareup/okhttp/internal/http/HttpEngine; or its super classes (declaration of 'com.squareup.okhttp.internal.http.HttpEngine' appears in /data/app/com.company.app.customerapp-1/base.apk)
            at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.newHttpEngine(HttpURLConnectionImpl.java:362)
            at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.initHttpEngine(HttpURLConnectionImpl.java:312)
            at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:377)
            at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:497)
            at retrofit.client.UrlConnectionClient.readResponse(UrlConnectionClient.java:73)
            at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:38)
            at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:321)
            at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:240)
            at java.lang.reflect.Proxy.invoke(Proxy.java:393)
            at $Proxy0.getTest(Unknown Source)
            at com.adoperator.tidyapp.TestActivity$TestRequest.loadDataFromNetwork(TestActivity.java:67)
            at com.adoperator.tidyapp.TestActivity$TestRequest.loadDataFromNetwork(TestActivity.java:54)
            at com.octo.android.robospice.request.CachedSpiceRequest.loadDataFromNetwork(CachedSpiceRequest.java:48)
            at com.octo.android.robospice.request.DefaultRequestRunner.processRequest(DefaultRequestRunner.java:150)
            at com.octo.android.robospice.request.DefaultRequestRunner$1.run(DefaultRequestRunner.java:217)
            at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
            at java.util.concurrent.FutureTask.run(FutureTask.java:237)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
            at java.lang.Thread.run(Thread.java:818)
D/Retrofit: ---- END ERROR

dependencies:

compile 'com.octo.android.robospice:robospice:1.4.14'
compile 'com.octo.android.robospice:robospice-cache:1.4.14'
compile 'com.octo.android.robospice:robospice-retrofit:1.4.14'

I suspect based on the exception that there is something wrong with the compiler, but I just tested on another computer with a fresh install of Java and Android Studio on the same project but same problems still...

This error is driving me crazy...

Anyone knows anything that could be of help? Any help is highly appreciated.

EDIT

MainActivity.java:

SpiceManager spiceManager = new SpiceManager(TestAPIService.class);

protected void onStart() {
    super.onStart();

    spiceManager.start(this);

    spiceManager.execute(new TestRequest(), new RequestListener<ResponseData>() {
        ...
    });
}

TestAPIService.java:

public class TestAPIService extends RetrofitGsonSpiceService {

    @Override
    public void onCreate() {
        super.onCreate();
        addRetrofitInterface(TestAPI.class);
    }

    @Override
    protected String getServerUrl() {
        return "http://192.168.0.2";
    }
}

TestAPI.java:

public interface TestAPI {
    @GET("/test")
    ResponseData getTest();
}

TestRequest.java:

public class TestRequest extends RetrofitSpiceRequest<ResponseData, TestAPI> {

    public TestRequest() {
        super(ResponseData.class, TestAPI.class);
    }


    @Override
    public ResponseData loadDataFromNetwork() throws Exception {
        ResponseData response;

        try {
            response = getService().getTest();
        }
        catch (Exception e) {
            e.printStackTrace();
            throw e;
        }

        return response;
    }
}

Solution

  • The NoSuchMethodError is happening because HttpURLConnectionImpl is trying to invoke a constructor on HttpEngine that is not defined. Now your project depends on:

    com.octo.android.robospice:robospice-retrofit:1.4.14
    

    Which depends on:

    com.squareup.retrofit:retrofit:1.6.1
    

    Which depends on both:

    com.squareup.okhttp:okhttp:2.0.0
    

    and

    com.squareup.okhttp:okhttp-urlconnection:2.0.0
    

    As of version 2.0.0, HttpURLConnectionImpl is in the okhttp-urlconnection module and HttpEngine is in the okhttp module. The retrofit.client.UrlConnectionClient portion of your stack trace correctly matches retrofit:1.6.1, but the com.squareup.okhttp.internal.huc.HttpURLConnectionImpl portion doesn't match okhttp-urlconnection:2.0.0; it matches okhttp-urlconnection:2.4.0. The constructor that the NoSuchMethodError is complaining about is indeed defined in okhttp:2.4.0, so that means there is a different HttpEngine on your classpath, most likely from a different version of okhttp that is getting pulled in by a transitive dependency. You should be able to fix the problem by specifying the following dependencies:

    compile('com.squareup.okhttp:okhttp:2.0.0') {
        force = true
    }
    compile('com.squareup.okhttp:okhttp-urlconnection:2.0.0') {
        force = true
    }
    

    If that doesn't work for whatever reason, the solution to your problem will still be to get your versions of okhttp and okhttp-urlconnection synced up and at a version that is compatible with your version of retrofit. Declare dependencies similar to above, find the jars that contain HttpURLConnectionImpl and HttpEngine, figure out how they're getting pulled in to your build, and use exclusions to get rid of problematic transitive dependencies.