title: AsyncRestTemplate ListenableFuture<T> Callback + Timeout
body: <p>I have configured an AsyncRestTemplate like this, here just an illustration to show that I am using an <em>HttpComponentsAsyncClientHttpRequestFactory</em> with <em>connectTimeout</em> and <em>readTimeout</em> being initialized with values - using Spring 4.0.8 RELEASE:</p>
  
  <pre><code>    &lt;bean id="myAsynchRequestFactory" class="org.springframework.http.client.HttpComponentsAsyncClientHttpRequestFactory"&gt;
          &lt;property name="httpAsyncClient" ref="myCloseableHttpAsynchClient"&gt;&lt;/property&gt;
          &lt;property name="connectTimeout" value="444"&gt;&lt;/property&gt;
          &lt;property name="readTimeout" value="555"&gt;&lt;/property&gt;
      &lt;/bean&gt;
  
      &lt;bean id="myAsynchRestTemplate" class="org.springframework.web.client.AsyncRestTemplate"&gt;
          &lt;constructor-arg&gt;
              &lt;ref bean="myAsynchRequestFactory"/&gt;
          &lt;/constructor-arg&gt;
      &lt;/bean&gt;
  </code></pre>
  
  <p>I also have configured a <em>RequestConfig</em> as the spring code suggests that the former method is deprecated, so I added it like this:</p>
  
  <pre><code>&lt;bean id="myRequestConfigBuilder" class="org.apache.http.client.config.RequestConfig" factory-method="custom"&gt;
      &lt;property name="connectionRequestTimeout" value="555"&gt;&lt;/property&gt;
      &lt;property name="connectTimeout" value="400"&gt;&lt;/property&gt;
      &lt;property name="socketTimeout" value="555"&gt;&lt;/property&gt;
  &lt;/bean&gt;
  
  &lt;bean id="myRequestConfig" factory-bean="myRequestConfigBuilder" factory-method="build"&gt;
  &lt;/bean&gt;
  
  &lt;bean id="myHttpAsyncClientBuilder" class="org.apache.http.impl.nio.client.HttpAsyncClientBuilder"&gt;
      &lt;property name="connectionManager" ref="myHttpAsyncConnectionManager"&gt;&lt;/property&gt;
      &lt;property name="defaultRequestConfig" ref="myRequestConfig"&gt;&lt;/property&gt;
  &lt;/bean&gt;
  
  &lt;bean id="myHttpAsyncClientBuilder" class="org.apache.http.impl.nio.client.HttpAsyncClientBuilder"&gt;
      &lt;property name="connectionManager" ref="myHttpAsyncConnectionManager"&gt;&lt;/property&gt;
      &lt;property name="defaultRequestConfig" ref="myRequestConfig"&gt;&lt;/property&gt;
  &lt;/bean&gt;
  &lt;bean id="myCloseableHttpAsynchClient" factory-bean="myHttpAsyncClientBuilder" factory-method="build"&gt;
  &lt;/bean&gt;
  </code></pre>
  
  <p>Now I am using the AsyncRestTemplate together with its <em>addCallback()</em> method like this (as illustration):</p>
  
  <pre><code>  response = myAsynchRestTemplate.getForEntity( ... );
    response.addCallback(new org.springframework.util.concurrent.ListenableFutureCallback&lt;ResponseEntity&lt;?&gt;&gt;() {
  
                      @Override
                      public void onSuccess(ResponseEntity&lt;?&gt; result) {
                          System.out.println("SUCCESS");
                      }
  
                      @Override
                      public void onFailure(Throwable ex) {
                          System.out.println("FAILURE")
                      }
                  }
  </code></pre>
  
  <p>I would expect that onSuccess(...) is never called when the Service takes more than 555ms to reply. But that does not happen. Even if my service fakes a delay of let's say 5000ms, the onSuccess method will be called no matter what. </p>
  
  <p>I have searched the web for possible solutions to add some kind of timeout to a callback, but didn't find anything appropriate. I tried to read cross the org.springframework.util.concurrent.* code in any versions since 4.0 but didn't yet find anything that would prevent the registered callback from execution.</p>
  
  <p>I already have seen the following Stackoverflow Questions:</p>
  
  <p><a href="https://stackoverflow.com/questions/29380653/how-to-cancel-asyncresttemplate-http-request-if-they-are-taking-too-much-time">How to cancel AsyncRestTemplate HTTP request if they are taking too much time?</a> This one suggests that the timeout should work</p>
  
  <p><a href="https://stackoverflow.com/questions/12380726/listenablefuture-futurecallback-and-timeouts">ListenableFuture, FutureCallback and timeouts</a> This one is using some Google Guava example, but I am using org.springframework.util.concurrent.ListenableFuture</p>
  
  <p>Does anybody have some solution for this problem?</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>I have found the root cause why this does not work...</p>
  
  <p>The <strong>HttpComponentsAsyncClientHttpRequestFactory</strong> does not take the RequestConfig I have provided. Instead, it is always null and such beeing recreated as RequestConfig.DEFAULT. This happens here:</p>
  
  <p>From HttpComponentesAsyncClientHttpRequestFactory:</p>
  
  <pre><code>@Override
  public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) throws IOException {
      HttpAsyncClient asyncClient = getHttpAsyncClient();
      startAsyncClient();
      HttpUriRequest httpRequest = createHttpUriRequest(httpMethod, uri);
      postProcessHttpRequest(httpRequest);
  
  
  
      /** HERE: It tries to create a HttpContext **/
      HttpContext context = createHttpContext(httpMethod, uri);
  
  
  
  
      if (context == null) {
          context = HttpClientContext.create();
      }
      // Request configuration not set in the context
      if (context.getAttribute(HttpClientContext.REQUEST_CONFIG) == null) {
          // Use request configuration given by the user, when available
          RequestConfig config = null;
          if (httpRequest instanceof Configurable) {
              config = ((Configurable) httpRequest).getConfig();
          }
          if (config == null) {
              config = RequestConfig.DEFAULT;
          }
          context.setAttribute(HttpClientContext.REQUEST_CONFIG, config);
      }
      return new HttpComponentsAsyncClientHttpRequest(asyncClient, httpRequest, context);
  }
  </code></pre>
  
  <p>But the method createHttpContext(httpMethod, uri) always returns null:</p>
  
  <pre><code>/**
   * Template methods that creates a {@link HttpContext} for the given HTTP method and URI.
   * &lt;p&gt;The default implementation returns {@code null}.
   * @param httpMethod the HTTP method
   * @param uri the URI
   * @return the http context
   */
  protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
      return null;
  }
  </code></pre>
  
  <p>Thus, the HttpContext is recreated and gets a <strong>RequestConfig.DEFAULT</strong> attached.</p>
  
  <p>Now <strong>compare</strong> this <strong>with the non-Asynch</strong> Version, <strong>HttpComponentsClientHttpRequestFactory</strong>. <em>This one recreates a RequestConfig with Timeouts:</em></p>
  
  <pre><code>@Override
  public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
      CloseableHttpClient client = (CloseableHttpClient) getHttpClient();
      Assert.state(client != null, "Synchronous execution requires an HttpClient to be set");
      HttpUriRequest httpRequest = createHttpUriRequest(httpMethod, uri);
      postProcessHttpRequest(httpRequest);
      HttpContext context = createHttpContext(httpMethod, uri);
      if (context == null) {
          context = HttpClientContext.create();
      }
      // Request configuration not set in the context
      if (context.getAttribute(HttpClientContext.REQUEST_CONFIG) == null) {
          // Use request configuration given by the user, when available
          RequestConfig config = null;
          if (httpRequest instanceof Configurable) {
              config = ((Configurable) httpRequest).getConfig();
          }
          if (config == null) {
  
  
  
  
              /** LOOK HERE - THE SYNC WORLD HAS THIS WORKAROUND */
              if (this.socketTimeout &gt; 0 || this.connectTimeout &gt; 0) {
                  config = RequestConfig.custom()
                          .setConnectTimeout(this.connectTimeout)
                          .setSocketTimeout(this.socketTimeout)
                          .build();
              }
  
  
  
              else {
                  config = RequestConfig.DEFAULT;
              }
          }
          context.setAttribute(HttpClientContext.REQUEST_CONFIG, config);
      }
      if (this.bufferRequestBody) {
          return new HttpComponentsClientHttpRequest(client, httpRequest, context);
      }
      else {
          return new HttpComponentsStreamingClientHttpRequest(client, httpRequest, context);
      }
  }
  </code></pre>
  
  <p>When I am using a <strong>SimpleClientHttpRequestFactory</strong> instead the timeouts I configure are taken and rather than <em>onSuccess(...)</em>, the <em>onFailure(...)</em> method is called with a <em>SocketTimeoutException</em></p>
  
  <p>This is totally puzzling - maybe anyone can give a hint why the HttpComponentsAsyncClientHttpRequestFactory is implemented as is?</p>
  
  <p>Is there any example of the proper use of the RequestConfig Object?</p>