通过Google App Engine上的OKClient使用OkHttp客户端抛出"java.lang.NoClassDefFoundError:java.net.ProxySelector"是一个受限制的类错误

man*_*yar 10 google-app-engine retrofit okhttp

我试图在谷歌应用引擎(1.9.22)上使用OKHTTP(版本2.4.0)进行改造(1.9.0).

这是我如何使用它:

    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();
Run Code Online (Sandbox Code Playgroud)

这会引发以下错误:

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)
Run Code Online (Sandbox Code Playgroud)

我从错误中收集到"java.net.ProxySelector"未列入白名单以用于google appengine.

问题1)是否可以在谷歌应用引擎(1.9.22)上使用OKHTTP(版本2.4.0)进行改造(1.9.0)?即,是否有解决此错误的方法

如果没有,问题2)还有其他方法:

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

(b) set connection and socket timeouts for the client used from (a) ?
Run Code Online (Sandbox Code Playgroud)

通过搜索我遇到的链接:(1)客户端的改造超时配置 (2)Google App Engine URL Fetch Java API

sum*_*tta 5

您可以将HttpUrlConnection与Retrofit2结合使用,以在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

}


Ale*_*kov 0

您可以使用以下代码片段来运行具有 GAE 限制的 Retorifit2。它包含许多可以在生产中免费删除的调试内容,并且没有实现真正的异步调用。

   okhttp3.Call.Factory gaeCallFactory = new okhttp3.Call.Factory() {
            @Override
            public okhttp3.Call newCall(final Request request) {

                final URL url = request.url().url();
                final String method = url.toString();

                return new okhttp3.Call() {
                    @Override
                    public Request request() {
                        return request;
                    }

                    @Override
                    public Response execute() throws IOException {
                        final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                        connection.setUseCaches(false);
                        if (request.body() != null) {
                            //TODO ajust for different needs   
                            connection.setRequestProperty("Content-Type", "application/json");
                            connection.setDoOutput(true);
                            BufferedSink outbuf;
                            ByteArrayOutputStream out = new ByteArrayOutputStream();
                            outbuf = Okio.buffer(Okio.sink(out));
                            request.body().writeTo(outbuf);
                            outbuf.close();
                            logger.info("Calling " + method + "\n" + new String(out.toByteArray()));
                            outbuf = Okio.buffer(Okio.sink(connection.getOutputStream()));
                            request.body().writeTo(outbuf);
                            outbuf.close();
                        } else {
                            logger.info("Calling " + method);
                        }

                        final BufferedSource source = Okio.buffer(Okio.source(connection.getInputStream()));
                        if (connection.getResponseCode() != HttpServletResponse.SC_OK) {
                            throw new IOException("Fail to call " + method + " :: " + 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();
                        logger.info("Call response code: " + response.code() + " message: " + response.message());
                        return response;
                    }

                    @Override
                    public void enqueue(Callback responseCallback) {
                        try {
                            responseCallback.onResponse(this, execute());
                        } catch (IOException e) {
                            responseCallback.onFailure(this, e);
                        }
                    }

                    @Override
                    public void cancel() {

                    }

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

                    @Override
                    public boolean isCanceled() {
                        return false;
                    }
                };
            }
        };
        Retrofit retrofit = new Retrofit.Builder()
                .callFactory(gaeCallFactory)
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(ENDPOINT_URI)
                .build();
Run Code Online (Sandbox Code Playgroud)