2015-06-18 6 views
8

Próbuję użyć OKHTTP (wersja 2.4.0) podczas modernizacji (1.9.0) na silniku aplikacji Google (1.9.22).Korzystanie z klienta OkHttp za pośrednictwem OKClient w Google App Engine zgłasza "java.lang.NoClassDefFoundError: java.net.ProxySelector" jest zastrzeżonym błędem klasy

Oto jak go używać:

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(); 

To rzuca się następujący błąd:

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) 

wnoszę z błędem, że „java.net.ProxySelector” nie jest biało-wymienione do użytku w Google Appengine.

Pytanie 1) Czy możliwe jest korzystanie z OKHTTP (wersja 2.4.0) w czasie modernizacji (1.9.0) na silniku aplikacji Google (1.9.22)? czyli jest tam pracę wokół tego błędu

jeśli nie, Pytanie 2) Czy istnieje inny sposób:

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

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

linki mam natknąć się poprzez wyszukiwania: (1) Retrofit timeout configuration for clients (2) Google App Engine URL Fetch Java API

Odpowiedz

0

Możesz użyć następującego fragmentu kodu, aby uruchomić Retorifit2 z ograniczeniami GAE. Zawiera wiele narzędzi do debugowania, które można usunąć podczas produkcji i nie implementuje prawdziwego połączenia asynchronicznego.

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(); 
4

Można użyć HttpURLConnection z Retrofit2 używać go w 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); 
    } 
} 

}

0

Musisz użyć AppEngine URLFetchClient zamiast OkHttpClient. Tak:

import retrofit.appengine.UrlFetchClient; 
RestAdapter restAdapter = new RestAdapter.Builder() 
      .setLogLevel(RestAdapter.LogLevel.FULL) 
      .setConverter(new JacksonConverter()) 
      .setEndpoint(ENDPOINT_PATH) 
      .setClient(new UrlFetchClient()) 
      .build(); 

Uwaga Funkcja ta działa tylko z Retrofit1, to nie będzie działać z Retrofit2 ponieważ jest połączony bezpośrednio do OkHttp jak wyjaśnił Jake Wharton here

+0

Uwaga dla przyszłych czytelników: 'URLFetchClient' nie zadziała w przypadku testów jednostkowych. Jeśli testujesz to, gdy aplikacja jest uruchomiona, jesteś gotowy. –