Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using OkHttp client via OKClient on Google App Engine throws a "java.lang.NoClassDefFoundError: java.net.ProxySelector" is a restricted class error

I am trying to use OKHTTP (version 2.4.0) along retrofit (1.9.0) on google app engine (1.9.22).

Here is the how i use it:

    OkHttpClient okHttpClient = new OkHttpClient();
    okHttpClient.setConnectTimeout(COMPOSER_MODULE_CONNECTION_TIMEOUT,  TimeUnit.SECONDS);
    okHttpClient.setReadTimeout(COMPOSER_MODULE_SOCKET_TIMEOUT, TimeUnit.SECONDS);

    RestAdapter restAdapter = new RestAdapter.Builder()
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .setConverter(new JacksonConverter())
                .setEndpoint(ENDPOINT_PATH)
                .setClient(new OkClient(okHttpClient))
                .build();

This throws the following error:

java.lang.NoClassDefFoundError: java.net.ProxySelector is a restricted class. Please see the Google App Engine developer's guide for more details.
at com.google.apphosting.runtime.security.shared.stub.java.net.ProxySelector.<clinit>(ProxySelector.java)
at com.squareup.okhttp.OkHttpClient.copyWithDefaults(OkHttpClient.java:614)
at com.squareup.okhttp.Call.<init>(Call.java:50)
at com.squareup.okhttp.OkHttpClient.newCall(OkHttpClient.java:595)
at retrofit.client.OkClient.execute(OkClient.java:53)

I gather from the error that "java.net.ProxySelector" is not white-listed for use on google appengine.

Question 1) Is it possible to use OKHTTP (version 2.4.0) along retrofit (1.9.0) on google app engine (1.9.22)? i.e, is there a work around for this error

if not, Question 2) Are there any other way to:

(a) use async HTTP calls with google appengine (with URLFetchService, for instance) ?

(b) set connection and socket timeouts for the client used from (a) ?

The links i have come across via search: (1) Retrofit timeout configuration for clients (2) Google App Engine URL Fetch Java API

like image 496
manyar Avatar asked Jun 18 '15 09:06

manyar


1 Answers

You can use HttpUrlConnection with Retrofit2 to use it in Google APP Engine

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.servlet.http.HttpServletResponse;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.BufferedSink;
import okio.BufferedSource;
import okio.Okio;


public class RetrofitCall implements Call {
Request request;

RetrofitCall(Request request) {
    this.request = request;
}

@Override
public Request request() {
    return request;
}

@Override
public Response execute() throws IOException {
    URL url = request.url().url();
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setUseCaches(false);
    connection.setDoOutput(true);
    connection.setRequestMethod(request.method());

    Headers headers = request.headers();
    if (headers != null) {
        for (int i = 0; i < headers.size(); i++) {
            String name = headers.name(i);
            connection.setRequestProperty(name, headers.get(name));
        }
    }

    if (request.body() != null) {
        BufferedSink outbuf;
        outbuf = Okio.buffer(Okio.sink(connection.getOutputStream()));
        request.body().writeTo(outbuf);
        outbuf.close();
    }

    connection.connect();

    final BufferedSource source = Okio.buffer(Okio.source(connection.getInputStream()));
    if (connection.getResponseCode() != HttpServletResponse.SC_OK) {
        throw new IOException("Fail to call " + " :: " + source.readUtf8());
    }
    Response response = new Response.Builder()
            .code(connection.getResponseCode())
            .message(connection.getResponseMessage())
            .request(request)
            .protocol(Protocol.HTTP_1_1)
            .body(new ResponseBody() {
                @Override
                public MediaType contentType() {
                    return MediaType.parse(connection.getContentType());
                }

                @Override
                public long contentLength() {
                    return connection.getContentLengthLong();
                }

                @Override
                public BufferedSource source() {
                    return source;
                }
            })
            .build();
    return response;
}

@Override
public void enqueue(Callback responseCallback) {

}

@Override
public void cancel() {

}

@Override
public boolean isExecuted() {
    return false;
}

@Override
public boolean isCanceled() {
    return false;
}

public static class Factory implements Call.Factory {
    @Override
    public Call newCall(Request request) {
        return new RetrofitCall(request);
    }
}

}

like image 121
sumit matta Avatar answered Nov 03 '22 18:11

sumit matta