javagoogle-app-enginegoogle-authenticationgoogle-http-client

How to increase ReadTimeout in Google HTTP Client


I have my application running in GAE. This application makes REST call to my CloudML.

Here is the code for that

GoogleCredential credential = GoogleCredential.getApplicationDefault()
        .createScoped(Collections.singleton(CLOUDML_SCOPE));
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
HttpRequestFactory requestFactory = httpTransport.createRequestFactory(
        credential);
GenericUrl url = new GenericUrl(cloudMLRestUrl);

JacksonFactory jacksonFactory = new JacksonFactory();
JsonHttpContent jsonHttpContent = new JsonHttpContent(jacksonFactory, getPayLoad());

ByteArrayOutputStream baos = new ByteArrayOutputStream();

jsonHttpContent.setWrapperKey("instances");
jsonHttpContent.writeTo(baos);
LOG.info("Executing request... " + baos.toString());
HttpRequest request = requestFactory.buildPostRequest(url, jsonHttpContent);

HttpResponse response = request.execute();  

Often the above code results in ReadTimeout exception.

java.net.SocketTimeoutException: Read timed out at 
java.net.SocketInputStream.socketRead0(Native Method) ~[na:1.8.0_121] at 
java.net.SocketInputStream.socketRead(SocketInputStream.java:116) 
~[na:1.8.0_121] at 
java.net.SocketInputStream.read(SocketInputStream.java:171) ~[na:1.8.0_121] 
at 

It seems we can add HttpRequestInitializer with custom timeout, but we need to pass GoogleCredential while create HttpRequestFactory HttpRequestFactory requestFactory = httpTransport.createRequestFactory(GoogleCredential);

Hence I can't use custom HTTPRequestInitializer. How can I increase the readTimeout for HttpRequestFactory created using GoogleCredential HTTPRequestInitializer?


Solution

  • I haven't tried this, but I'd expect you to be able to effectively chain the request initializers together:

    final GoogleCredential credential = ...;
    HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
    HttpRequestFactory requestFactory = httpTransport.createRequestFactory(
        new HttpRequestInitializer() {
            @Override public void initialize(HttpRequest request) {
                credential.initialize(request);
                request.setReadTimeout(...);
            }
        });
    

    Or as a lambda expression:

    final GoogleCredential credential = ...;
    HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
    HttpRequestFactory requestFactory = httpTransport.createRequestFactory(
        request -> {
            credential.initialize(request);
            request.setReadTimeout(...);
        });
    

    In other words, when a new request is created, the credential is able to set headers etc, and then you set the read timeout as well.